0

I seem to have encountered a problem concerning a deadlock when trying to run 2 threads which are based on each other.

The code is like this:

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();
        }

    }
}

I do not get any error from the Console, but it only prints the first syso on the the thread I run first. The 2nd thread doesn't seem to run at all. It doesn't retrieve the package or insert it and doesn't release the lock. Any help/advice on how to get past this issue is appreciated and if anyone has a good design pattern tips I'll be more then happy to learn.

By the way, the program basically simulates a box which can contain 1 package at once, if it's full the customer pulls the package, if it's empty the shop will put in 1 package.

EDIT:

its diffrent from what suggested as duplicate since in the the other question there is no java code for the main thread so it doesnt include the answer to my own question.

Daniel Netzer
  • 2,151
  • 14
  • 22

1 Answers1

2

You're calling run() method of Shop and Customer in a single thread without creating thread.

Replace shop.run(); with new Thread(shop).start()

Replace customer.run(); with new Thread(customer).start()

to start new Thread for them

or you can extend Thread instead of implementing Runnable (it implements Runnable anyway) and override the Run method just like you and invoke start() method of them directly.

Burak Tamtürk
  • 1,237
  • 8
  • 19