程序会启动20个线程,20个线程都使用同一个sync的object(名字为SYNC)。 线程启动代码如下:
final TC[] ts = new TC[20]; for (int i = 0; i < ts.length; i++) { TC target = new TC("TC " + i, SYNC1); Thread thread = new Thread(target); ts[i] = target; thread.start();}
------------------------------------------------------------
接下来马上启动另外一个线程用于做notify操作。
// 一个用于停止的Thread new Thread(new Runnable() { public void run() { synchronized (SYNC1) { int i = 10; while (i > 0) { System.out.println("Now will notify the thread " + i); ts[i].notifySelf(); try { SYNC1.wait(10000); } catch (InterruptedException e) { e.printStackTrace(); } i--; } } } }).start();
------------------------------------------------------------
启动的TC线程代码如下:class TC implements Runnable { private final String name; private final Object sync; private boolean isRunning = false; public TC(String name, Object sync) { this.name = name; this.sync = sync; } public void run() { synchronized (sync) { while (true) { // 每个线程默认都加入线程池排队。这样有助于打乱线程在主线程中启动的顺序,方便后面的观测。 if (!isRunning) { try { sync.wait(1000); } catch (InterruptedException e) { e.printStackTrace(); } isRunning = true; } System.out.println(name + " Running ......."); try { sync.wait(); } catch (InterruptedException e) { e.printStackTrace(); }// Wait 1 second } } } public void notifySelf() { synchronized (sync) { System.out.println("Coming to notify the thread " + name); sync.notify(); } }}
---------------------------分割线---------------------------------
输出日志如下(//部分是我加的注释,不是实际输出):
[color=darkred]Now will notify the thread 10 //首先试着notify第10个TC
Coming to notify the thread TC 10 // 也确实调用了SYNC的notify操作,但是因为当前还没有任何线程在wait,所以这个notify信号就被丢弃掉了。这个notify过去就过去了。不会影响后面的任何操作了。
TC 1 Running .......
TC 5 Running .......
TC 0 Running .......
TC 2 Running .......
TC 4 Running .......
TC 6 Running .......
TC 8 Running .......
TC 10 Running .......
TC 12 Running .......
TC 14 Running .......
TC 7 Running .......
TC 9 Running .......
TC 11 Running .......
TC 13 Running .......
TC 15 Running .......
TC 17 Running .......
TC 3 Running .......
TC 18 Running .......
TC 16 Running .......
TC 19 Running ....... //启动20线程,这20个线程启动的顺序已经被打乱了。不会从头到尾1-20的启动,而是如log显示1,5,0,2,4,6,8,10,12,14.........
//每个线程启动后会被wait(). wait的顺序是1,5,0,2,4,6,8,10,12,14.........
Now will notify the thread 9
Coming to notify the thread TC 9
TC 1 Running .......
Now will notify the thread 8
Coming to notify the thread TC 8
TC 5 Running .......
Now will notify the thread 7
Coming to notify the thread TC 7
TC 0 Running .......
Now will notify the thread 6
Coming to notify the thread TC 6
TC 2 Running .......
Now will notify the thread 5
Coming to notify the thread TC 5
TC 4 Running .......
Now will notify the thread 4
Coming to notify the thread TC 4
TC 6 Running .......
Now will notify the thread 3
Coming to notify the thread TC 3
TC 8 Running .......
Now will notify the thread 2
Coming to notify the thread TC 2
TC 10 Running .......
Now will notify the thread 1
Coming to notify the thread TC 1
TC 12 Running .......
//总共10个notify操作,但是因为启动的时候一个notify因为没有任何wait的线程给丢弃了,所以,这里只有9个notify起到了作用。他们是按照进入pool的顺序排队给notify。
//一个notify操作仅仅激活一个wait队列中的第一个线程。一对一操作。[/color]
-------------------------------分割线------------------------------
使用notifyAll代替notify。
日志输出:
[color=darkred]Now will notify the thread 10
Coming to notify the thread TC 10 //第一个notifyAll的操作还是被丢弃了
TC 0 Running .......
TC 1 Running .......
TC 3 Running .......
TC 5 Running .......
TC 7 Running .......
TC 9 Running .......
TC 11 Running .......
TC 13 Running .......
TC 15 Running .......
TC 17 Running .......
TC 19 Running .......
TC 2 Running .......
TC 4 Running .......
TC 6 Running .......
TC 8 Running .......
TC 10 Running .......
TC 12 Running .......
TC 14 Running .......
TC 16 Running .......
TC 18 Running .......
Now will notify the thread 9
Coming to notify the thread TC 9 //一个notifyAll的操作notify所以正在wait的线程。
TC 0 Running .......
TC 1 Running .......
TC 3 Running .......
TC 5 Running .......
TC 7 Running .......
TC 9 Running .......
TC 11 Running .......
TC 2 Running .......
TC 13 Running .......
TC 15 Running .......
TC 4 Running .......
TC 17 Running .......
TC 19 Running .......
TC 6 Running .......
TC 8 Running .......
TC 10 Running .......
TC 12 Running .......
TC 14 Running .......
TC 16 Running .......
TC 18 Running .......
[/color]