日期:2014-05-20  浏览次数:20812 次

notify问题
代码这样的
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()+"得到通知.........");
    }