我知道很多人都有这个话题的问题,你可能会感到无聊,但我试着理解它,因为几天仍然不知道它是如何工作的:(。我有一个计数器对象和其他对象另一个类(将来多于一个类)。现在每个对象都应该响应计数器执行。一个计数 - 每个对象运行方法的一步。这是我的代码:
public class Th {
private final static Object lock1 = new Object();
////////////////////////////////////////////////////////////////////////////////
private class Stop implements Runnable {
private int count, id;
public Stop(int id) {
this.count = 0;
this.id = id;
}
@Override public void run() {
synchronized(lock1){
while (count < 20) {
try {
lock1.wait();
}
catch (InterruptedException exception) {
System.out.println("Error!");
}
System.out.println(count + " stop " + id);
this.count++;
// try {
// Thread.sleep(360);
// }
// catch (InterruptedException exception) {
// System.out.println("Error!");
// }
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
private class Counter implements Runnable {
private int count;
public Counter() {
this.count = 0;
}
@Override public void run() {
synchronized(lock1){
while (count<15) {
lock1.notifyAll();
System.out.println(count + " counter");
this.count++;
// try {
// Thread.sleep(360);
// }
// catch (InterruptedException exception) {
// System.out.println("Error!");
// }
}
}
}
}
public void test() {
Stop s1 = new Stop(1);
Stop s2 = new Stop(2);
Stop s3 = new Stop(3);
Counter counter = new Counter();
(new Thread(s1)).start();
(new Thread(s2)).start();
(new Thread(counter)).start();
(new Thread(s3)).start();
}
}
它返回了类似的内容:
run:
0 counter
1 counter
2 counter
3 counter
4 counter
5 counter
6 counter
7 counter
8 counter
9 counter
10 counter
11 counter
12 counter
13 counter
14 counter
0 stop 1
我需要的是:
0 counter
0 stop 0
0 stop 1
0 stop 2
1 counter
1 stop 0
1 stop 1
1 stop 2
2 counter
2 stop 0
2 stop 1
2 stop 2
3 counter
...
答案 0 :(得分:4)
Counter
线程的整个循环在lock1
上同步。这意味着虽然在此循环中调用notifyAll
,但在Counter
线程中完成循环结束之前,其他线程无法重新获取锁。
使循环的每次迭代同步,而不是在循环外同步。
请注意,这是不够的,因为Counter线程可能会在所有Stop线程重新获取之前重新获取锁。您需要让Counter线程在另一个条件下等待,并在所有Stop线程显示计数时重新启动它。
您应该调查更高级别的抽象,例如CyclicBarrier和CountDownLatch。
答案 1 :(得分:3)
首先,解决此问题的最佳方法是使用更高级别的同步类,如JB Nizet所说。
但是如果你想“艰难地”做一个学习练习,你需要认识到这个问题需要Counter和Stop线程等待特定的“事件”。
Stop线程需要等到Counter线程告诉他们前进到下一站。
计数器线程需要等到所有停止线程已提前并停止。
当前实现的一个问题是,当所有Stop线程都已提前并停止时,Counter线程无需告诉它。相反,它假设当它看到一个通知事件时,可以发出下一个计数。