Java死锁,2个线程似乎互相阻塞

时间:2015-12-26 21:49:40

标签: java multithreading 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();
        }

    }
}

我没有从控制台收到任何错误,但它只打印我首先运行的线程上的第一个syso。第二个线程似乎根本没有运行。它不会检索包装或插入包装并且不会释放锁定。任何关于如何解决这个问题的帮助/建议都表示赞赏,如果有人有一个好的设计模式提示,我会更乐于学习。

顺便说一下,该程序基本上模拟了一个盒子,它可以同时包含1个包装,如果它已经满了,顾客拉包装,如果它是空的,商店将放入1个包装。 / p>

编辑:

它与建议重复的不同,因为在另一个问题中,主线程没有java代码,因此它不包括我自己的问题的答案。

1 个答案:

答案 0 :(得分:2)

您在单个线程中调用Shop和Customer的run()方法而不创建线程。

shop.run();替换为new Thread(shop).start()

customer.run();替换为new Thread(customer).start()

为他们开始新的线程

或者你可以扩展Thread而不是实现Runnable(它实现了Runnable)并像你​​一样覆盖Run方法并直接调用它们的start()方法。