notify()和notifyAll()有什么区别?

摘要:
//RunnableImplBnotify()Thread3=newThread(newRunnableImpl B(obj));synchronized(obj){System.out.println(“objtowaitonRunnableImplA”);尝试{Thread.sleep(3000);

先解释两个概念。

  • 等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池,等待池中的线程不会去竞争该对象的锁。
  • 锁池:只有获取了对象的锁,线程才能执行对象的 synchronized 代码,对象的锁每次只有一个线程可以获得,其他线程只能在锁池中等待


区别:

notify() 方法随机唤醒对象的等待池中的一个线程,进入锁池;notifyAll() 唤醒对象的等待池中的所有线程,进入锁池。

测试代码

public class TestNotifyNotifyAll {
 
    private static Object obj = new Object();
    
    public static void main(String[] args) {
        
        //测试 RunnableImplA wait()        
        Thread t1 = new Thread(new RunnableImplA(obj));
        Thread t2 = new Thread(new RunnableImplA(obj));
        t1.start();
        t2.start();
        
        //RunnableImplB notify()
        Thread t3 = new Thread(new RunnableImplB(obj));
        t3.start();
        
        
//        //RunnableImplC notifyAll()
//        Thread t4 = new Thread(new RunnableImplC(obj));
//        t4.start();
    }
    
}
 
 
class RunnableImplA implements Runnable {
 
    private Object obj;
    
    public RunnableImplA(Object obj) {
        this.obj = obj;
    }
    
    public void run() {
        System.out.println("run on RunnableImplA");
        synchronized (obj) {
            System.out.println("obj to wait on RunnableImplA");
            try {
                obj.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("obj continue to run on RunnableImplA");
        }
    }
}
 
class RunnableImplB implements Runnable {
 
    private Object obj;
    
    public RunnableImplB(Object obj) {
        this.obj = obj;
    }
    
    public void run() {
        System.out.println("run on RunnableImplB");
        System.out.println("睡眠3秒...");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (obj) {
            System.out.println("notify obj on RunnableImplB");
            obj.notify();
        }
    }
}
 
class RunnableImplC implements Runnable {
 
    private Object obj;
    
    public RunnableImplC(Object obj) {
        this.obj = obj;
    }
    
    public void run() {
        System.out.println("run on RunnableImplC");
        System.out.println("睡眠3秒...");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (obj) {
            System.out.println("notifyAll obj on RunnableImplC");
            obj.notifyAll();
        }
    }
}

结果:仅调用一次 obj.notify(),线程 t1 或 t2 中的一个始终在等待被唤醒,程序不终止

run on RunnableImplA
obj to wait on RunnableImplA
run on RunnableImplA
obj to wait on RunnableImplA
run on RunnableImplB
睡眠3秒...
notify obj on RunnableImplB
obj continue to run on RunnableImplA

 把 t3 注掉,启动 t4 线程。调用 obj.notifyAll() 方法

public class TestNotifyNotifyAll {
 
    private static Object obj = new Object();
    
    public static void main(String[] args) {
        
        //测试 RunnableImplA wait()        
        Thread t1 = new Thread(new RunnableImplA(obj));
        Thread t2 = new Thread(new RunnableImplA(obj));
        t1.start();
        t2.start();
        
//        //RunnableImplB notify()
//        Thread t3 = new Thread(new RunnableImplB(obj));
//        t3.start();
        
        
        //RunnableImplC notifyAll()
        Thread t4 = new Thread(new RunnableImplC(obj));
        t4.start();
    }
    
}

 结果:t1、t2线程均可以执行完毕

run on RunnableImplA
obj to wait on RunnableImplA
run on RunnableImplA
obj to wait on RunnableImplA
run on RunnableImplC
睡眠3秒...
notifyAll obj on RunnableImplC
obj continue to run on RunnableImplA
obj continue to run on RunnableImplA


原文链接
 


notify()和notifyAll()有什么区别?第1张

 

所有资源资源汇总于公众号

notify()和notifyAll()有什么区别?第2张

 

免责声明:文章转载自《notify()和notifyAll()有什么区别?》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇11正则表达式REAndroidStudio技巧之copy工程下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

复制一个datatable的指定行到另外一个datatable dodo

DataTable dt = oldDataTable;DataTable result = dt.Clone();//复制表的结构            resultTable.Rows.Add(dt.Rows[index].ItemArray);//ItemArray ----通过一个数组来获取或设置此行的所有值 //新建表   DataTable ...

windows线程yield以及Sleep(0)和SwitchToThread之间的区别

C++的自定义线程函数内调用了一个自定义的yield()接口。 在windows上是调用了SwitchToThread来实现的,linux是pthread_yield实现的。 Sleep(0):时间片只能让给优先级相同或更高的线程; SwitchToThread():只要有可调度线程,即便优先级较低,也会让其调度。 下面是MSDN上对Sleep函数的描述:...

Debug技巧

多线程调试 有些时候为了观察多个线程间变量的不同状态,以及锁的获取等,就会想到在代码里加个断点debug一下。  在IDE里断点停下来的时候,可以切换到另外的线程中,跑其他的代码,不会互相影响。这里是有个开关的,在Eclipse里默认开启, 在IntelliJ IDEA里默认是没有开启的。也就是说如果你在IDEA里代码里加断点,虽然一个线程的断了下来,但其...

Android Looper详解

在Android下面也有多线程的概念,在C/C++中,子线程可以是一个函数, 一般都是一个带有循环的函数,来处理某些数据,优先线程只是一个复杂的运算过程,所以可能不需要while循环,运算完成,函数结束,线程就销毁。对于那 些需要控制的线程,一般我们都是和互斥锁相互关联,从而来控制线程的进度,一般我们创建子线程,一种线程是很常见的,那就是带有消息循环的线程...

python中多线程,多进程,多协程概念及编程上的应用

1, 多线程  线程是进程的一个实体,是CPU进行调度的最小单位,他是比进程更小能独立运行的基本单位。  线程基本不拥有系统资源,只占用一点运行中的资源(如程序计数器,一组寄存器和栈),但是它可以与同属于一个进程的其他线程共享全部的资源。  提高程序的运行速率,上下文切换快,开销比较少,但是不够稳定,容易丢失数据,形成死锁。 直接上代码: impor...

Java多线程之控制执行顺序

 概念: 多线程在并发环境中的正常执行顺序是随机无序的,并不能按照期盼的结果输出。                因为启动一个线程时,线程并不会立即执行,而是等待CPU的资源调度,CPU能调度哪个线程,是通过多种复杂的算法计算而来。 (一)Thread的join()方法来解决这个问题        一般在多线程编程时,需要控制线程的先后执行顺序,比如:主线...