代码这样的
- Java code
package com.tdt.test;public class NotifyTest { public static final String LOCK="LOCK_MAIN"; public static void main(String[] args) { for(int i=0;i<=10;i++){ new Work("线程"+i).start(); } for(int i=0;i<=10;i++){ synchronized (LOCK) { LOCK.notify(); try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } } } }}class Work extends Thread{ public Work(String threadName) { super(threadName); } @Override public void run() { synchronized (NotifyTest.LOCK) { try { NotifyTest.LOCK.wait(); } catch (Exception e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+"得到通知........."); }}
我是想看看notify最后是不是都通知到了
这段代码放到锁外面,运行没问题,线程后面执行完了
- Java code
try { Thread.sleep(1000);} catch (Exception e) { e.printStackTrace();}
放到里面后
线程10感觉一直处于等待当中,没有得到通知
------解决方案--------------------------------------------------------
因为wait的时候,线程释放掉当前持有的锁,当从wait中醒来的时候,需要重新获取之前释放的锁
然而,Thread.sleep(1000)期间,notify的那个线程,一直持有该锁,导致wait一直获取不到锁,所以它还得等
------解决方案--------------------------------------------------------
个人觉得:
程序要执行完的话,一定是wait()在先,notify()在后。这样保证能够唤醒等待的线程。
根据测试的情况看,把那段等待的程序放在同步块里的话,在等待时,就象楼上所说,是不释放锁的。这样会导致Work线程得到锁的几率大大减小。notify()先于wait()都执行完了,那么后面运行的线程的wait()就没有机会唤醒了。
而如果把那段程序放在外面的话,主线程占有锁的时间大大缩短,而work线程得到所得几率大大增加,10个线程会先于主线程启动完(运行到wait()). 这些进入等待的线程都会得到主线程的notify()唤醒。会执行完。
楼主可以加一句测试是一下:
- Java code
@Override public void run() { synchronized (NotifyTest.LOCK) { try { System.out.println("****"); //这加一句看看效果。 NotifyTest.LOCK.wait(); } catch (Exception e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+"得到通知........."); }