Print odd and even using two threads in Java

2019-05-29 10:45发布

I am trying to do it using two threads like below. Can someone point the obvious mistake I am doing here?

public class OddEven {

public static boolean available = false;
public static Queue<Integer> queue = new LinkedList<Integer>();

static Thread threadEven = new Thread() {
    @Override
    public void run() {
        printEven();
    }

    public synchronized void printEven() {
        while (!available) {
            try {
                wait();
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
        }

        System.out.println(queue.remove());

        available = false;
        notifyAll();
    }
};

static Thread threadOdd = new Thread() {
    @Override
    public void run() {
        printOdd();
    }

    public synchronized void printOdd () {
        while (available) {
            try {
                wait();
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
        }

        System.out.println(queue.remove());

        available = true;
        notifyAll();
    }
};

public static void main(String[] args) {
    int n = 20;
    for (int i = 1; i < n; i++) {
        queue.add(i);
    }

    threadOdd.start();
    threadEven.start();

    try {
        Thread.sleep(60000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    try {
        threadOdd.join();
        threadEven.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

}

But this program is only printing 1 and quitting. After printing 1 the available should be true and printEven should wake up, print and set available to false. I don't understand what is going wrong here? I saw other solutions but want to know why my solution is not working.

1条回答
三岁会撩人
2楼-- · 2019-05-29 11:13

Putting synchronized on an instance method means that the thread calling that method has to acquire the lock on that instance; public void synchronized printOdd() is syntax sugar for

public void printOdd() {
    synchronized(this) {
        ...
    }
}

where this is different for each instance, since ThreadOdd and threadEven are two different objects and each one uses its own lock. The methods notifyAll and wait are called on the object that is being used as the lock. When one thread waits it never gets notified because the notification only applies to other threads waiting on the same lock as the notifying thread.

查看更多
登录 后发表回答