我正在尝试使用下面的两个线程来做到这一点。有人可以指出我在这里犯的明显错误吗?
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();
}
}
}
但是此程序仅打印1并退出。在打印1之后,available应该为true,printEven应该被唤醒,将print设置为false。我不明白这里出了什么问题?我看到了其他解决方案,但想知道为什么我的解决方案无法正常工作。
最佳答案
将同步放在实例方法上意味着调用该方法的线程必须获取该实例上的锁。 public void synchronized printOdd()
是语法糖
public void printOdd() {
synchronized(this) {
...
}
}
其中,每个实例的
this
不同,因为ThreadOdd和threadEven是两个不同的对象,并且每个对象都使用自己的锁。在用作锁的对象上调用notifyAll和wait方法。当一个线程等待时,它永远不会得到通知,因为该通知仅适用于与通知线程处于同一锁上的其他线程。