Reputation: 7335
I know it lot of people have problems with this topic and you might be bored, but I try to understand it since few days and still don't know how it works:(. I have a counter object, and other objects of another class (in the future more then one class). Now each object should respond for counters execution. One count - one step of each objects run method. That's my code:
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();
}
}
and it returns me something like:
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
what I need is:
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
...
Upvotes: 0
Views: 199
Reputation: 719386
First, the best way to solve this is to use the higher level synchronization classes, as JB Nizet says.
But if you want to do it "the hard way" as a learning exercise, you need to recognize that this problem requires the Counter and Stop threads to wait for specific "events".
The Stop threads need to wait until the Counter thread tells them to advance to the next stop.
The Counter thread needs to wait until all Stop threads have advanced and stopped.
One problem with your current implementation is that the Counter thread has nothing to tell it when all of the Stop threads have advanced and stopped. Instead, it assumes that when it sees a notify event that it is ok to issue the next count.
Upvotes: 3
Reputation: 692081
The entire loop of the Counter
thread is synchronizd on lock1
. This means that although you call notifyAll
in this loop, other threads can't reacquire the lock until the complete loop has ended in the Counter
thread.
Make each iteration of the loop synchronized, instead of synchronizing outside of the loop.
Note that this won't be sufficient, though, because the Counter thread might reacquire the lock before all the Stop threads have reacquired it. You'll need to make the Counter thread wait on another condition, and make it restart when all the Stop threads have displayed the count.
You should investigate higher-level abstractions, like CyclicBarrier and CountDownLatch.
Upvotes: 4