Java notify and notifyAll

来源:互联网 发布:js给对象添加隐藏属性 编辑:程序博客网 时间:2024/06/05 00:27

JAVA 多线程 notify 和 notifyAll 的区别


notify

Wakes up a single thread that is waiting on this object’s monitor.(唤醒一个等待着这个对象监听器的线程)Java API Doc

notifyAll

Wakes up all threads that are waiting on this object’s monitor. (唤醒所有等待着这个对象监听器线程)Java API Doc

测试代码片段

public class MainCode {    static final SysClass Sys = new SysClass() ;    public static void main(String[] args) throws Exception    {        ExecutorService threadExe = Executors.newCachedThreadPool() ;        threadExe.execute(new NotifyStudy(Sys , "Thread 1")) ;        threadExe.execute(new NotifyStudy(Sys , "Thread 2")) ;        threadExe.execute(new NotifyStudy(Sys , "Thread 3")) ;        threadExe.execute(new NotifyStudy(Sys , "Thread 4")) ;        threadExe.shutdown() ;        Thread.sleep(3000) ;        //Sys.TaskNotify() ;        //Sys.TaskNotifyAll() ;    }}public class SysClass{    /**     * 类 SysClass 的对象的构造函数     */    public SysClass()    {    }    public synchronized void TaskEnterWait(String name)    {        try        {            System.out.printf("%s is waiting" , name) ;            System.out.println() ;            wait() ;            System.out.printf("%s is begin running" , name) ;            System.out.println() ;            Thread.sleep(500) ;            System.out.printf("%s is still running , i get the moniter lock" , name) ;            System.out.println() ;        }        catch(Exception e)        {         }    }    public synchronized void TaskNotify()    {        try        {            notify() ;              }        catch(Exception e)        {        }    }    public synchronized void TaskNotifyAll()    {        try        {            notifyAll() ;              }        catch(Exception e)        {        }    }}public class NotifyStudy implements Runnable{    private SysClass Sys = null ;    private String Name = null ;    /**     * 类 NotifyStudy 的对象的构造函数     */    public NotifyStudy(SysClass sys , String name)    {        Sys = sys ;        Name = name ;    }    public void run()    {        Sys.TaskEnterWait(Name) ;    }}

两者的区别

由字面意可知,notify 只会唤醒一个调用了同一对象wait()方法进入 wait 状态的线程。
但是在唤醒了其他线程之后,依旧会执行当前线程的代码,直到释放了锁之后,被唤醒的现成才会被开始执行。
notify() 不会去打扰其他的调用了同一对象wait()方法的线程,其他 wait 线程依旧在等待 notify() or notifyAll()。
notify 测试代码结果 Use Sys.TaskNotify() ;
由上图结果可知,四个线程全部进入了 wait 状态,3S之后,主函数调用了 Sys 对象的 TaskNotify() 方法间接调用了该对象的 notify() 方法,此时,只有一个线程被唤醒且执行,其余三个线程依旧处于 wait 状态无法执行。


而如果调用的是TaskNotifyAll()函数间接调用对象的 notifyAll() 函数 。
notifyAll 测试代码结果 Use Sys.TaskNotifyAll() ;
由上图可知,4个线程在主函数调用了一次 notifyAll() 之后全部离开了 wait 状态开始竞争锁的拥有全 , 但依旧只能有一个线程拥有锁,也就是只能有一个线程开始执行任务,只有当该线程完成任务释放锁后,其余3个线程才能继续竞争锁的拥有权,最终四个线程全部执行了任务。
也就是一次 notifyAll() 函数调用,使所有被同一对象调用了 wait() 函数而进入 wait 状态的线程都不再受 wait() 限制,只要有锁空闲就可以去竞争。
注意:就算不受 wait() 函数限制,但以同一个对象作为锁的线程在一个时刻只能有一个线程拥有锁并且执行。


原创粉丝点击