2015-12-26 2 views
0

Кажется, что я столкнулся с проблемой касания тупика при попытке запустить 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-кода для основного потока, так что не включает ответ на свой вопрос.

+1

Вы вызываете метод 'run()' магазина и клиента в одном потоке без создания потока. Может, это проблема? –

+0

оба они реализуют Runnable –

+0

@ DanielNetzer Они просто класс Runnable. Если вы вызываете .run() напрямую, вы запускаете их в потоке, который вы вызываете. См. Мой ответ. –

ответ

2

Вы вызываете метод run() магазина и клиента в одном потоке без создания потока.

Заменить shop.run(); с new Thread(shop).start()

Заменить customer.run(); с new Thread(customer).start()

начать новую тему для них

или вы можете расширить тему вместо реализации Runnable (он реализует Runnable в любом случае) и переопределить метод Run точно так же, как вы, и сразу вызовите метод start().

+0

выдающийся, я играл с флагами .wait и .notify более 3 часов. Большое спасибо Бурак. –

Смежные вопросы