Кажется, что я столкнулся с проблемой касания тупика при попытке запустить 2 потока, которые основаны друг на друге.Java deadlock, 2 потока, кажется, блокируют друг друга
Код выглядит так:
Box.Java (Main)
package exe4;
public class Box {
private static boolean boxStatus;
static Thread boxThread = Thread.currentThread();
public Box(){
Box.boxStatus = true;
}
public static void main(String[] args) throws InterruptedException{
Box box = new Box();
Shop shop = new Shop(box, "Post Office");
Customer customer = new Customer(box, "Daniel Netzer");
shop.run();
customer.run();
Thread.sleep(60000);
}
public boolean isBoxStatus() {
return boxStatus;
}
public void setBoxStatus(boolean boxStatus) {
Box.boxStatus = boxStatus;
}
}
Shop.java
package exe4;
public class Shop implements Runnable{
private static Box box;
private static String name;
private static Object shopLock = new Object();
public Shop(Box box, String name){
Shop.box = box;
Shop.name = name;
}
public static Object getShopLockMonitor(){
return Shop.shopLock;
}
public String getName() {
return name;
}
public synchronized void setName(String name) {
Shop.name = name;
}
public static Box getBox() {
return box;
}
public synchronized void setBox(Box box) {
Shop.box = box;
}
public synchronized void depositBox(){
Shop.box.setBoxStatus(true);
synchronized(Customer.getCustomerLockMonitor()){
Customer.getCustomerLockMonitor().notifyAll();}
}
public synchronized void printDeposit(){
System.out.println("New package have been deposited into your box.");
}
@Override
public void run() {
while(Box.boxThread.isAlive()){
while(box.isBoxStatus()){
synchronized(Shop.getShopLockMonitor()){
try {
System.out.println("Box is full, waiting for customer withdrawal.");
Shop.getShopLockMonitor().wait();
} catch (InterruptedException e) {}
}
}
depositBox();
printDeposit();
}
}
}
Customer.java
package exe4;
public class Customer implements Runnable{
private static Box box;
private static String name;
private static Object customerLock = new Object();
public Customer(Box box, String name){
Customer.box = box;
Customer.name = name;
}
public static Object getCustomerLockMonitor(){
return Customer.customerLock;
}
public String getName() {
return name;
}
public synchronized void setName(String name) {
Customer.name = name;
}
public static Box getBox() {
return box;
}
public synchronized void setBox(Box box) {
Customer.box = box;
}
public synchronized void withdrawBox(){
Customer.box.setBoxStatus(false);
synchronized(Shop.getShopLockMonitor()){
Shop.getShopLockMonitor().notifyAll();}
}
public synchronized void printWithdraw(){
System.out.println("Package have been withdrawed from box.");
}
@Override
public void run() {
while(Box.boxThread.isAlive()){
while(!box.isBoxStatus()){
synchronized(Customer.getCustomerLockMonitor()){
try {
System.out.println("Box is empty, waiting for a new package to arrive.");
Customer.getCustomerLockMonitor().wait();
} catch (InterruptedException e) {}
}
}
withdrawBox();
printWithdraw();
}
}
}
Я не получить любую ошибку из Консоли, но она только печатает s первый syso в потоке, который я запускаю первым. Второй поток, похоже, вообще не работает. Он не извлекает пакет или не вставляет его и не освобождает блокировку. Любая помощь/советы о том, как преодолеть эту проблему, оценивается, и если у кого-то есть хорошие советы по дизайну, я буду более счастлив узнать.
Кстати, программа в основном имитирует ящик, который может содержать 1 пакет одновременно, если он заполнен, клиент достает пакет, если он пуст, магазин будет помещен в 1 пакет.
EDIT:
его diffrent от того, что предлагается в качестве дубликата, так как в другом вопросе нет Java-кода для основного потока, так что не включает ответ на свой вопрос.
Вы вызываете метод 'run()' магазина и клиента в одном потоке без создания потока. Может, это проблема? –
оба они реализуют Runnable –
@ DanielNetzer Они просто класс Runnable. Если вы вызываете .run() напрямую, вы запускаете их в потоке, который вы вызываете. См. Мой ответ. –