本文主要介绍Java中notify()和notifyAll()的区别。用示例代码详细介绍,感兴趣的朋友可以参考一下。
notify()和notifyAll()有什么区别?
先解释两个概念。
等待池:假设一个线程A调用一个对象的wait()方法,它会释放该对象的锁,进入该对象的等待池,等待池中的线程不会争夺该对象的锁。
锁池:只有获得对象的锁,线程才能执行对象的同步代码。一次只有一个线程可以获得对象的锁,其他线程只能在锁池中等待。
然后再来说notify和notifyAll的区别
如果线程调用了对象的wait()方法,线程就会在对象的等待池中,等待池中的线程不会竞争对象的锁。
当一个线程调用一个对象的notifyAll()方法(唤醒所有等待线程)或notify()方法(随机只唤醒一个等待线程)时,被唤醒的线程会进入该对象的锁池,锁池中的线程会争夺该对象的锁。也就是说,一旦调用notify,只有一个线程会从等待池进入锁池,notifyAll会将对象的等待池中的所有线程都移到锁池中,等待锁竞争。
高优先级线程竞争对象锁的可能性很高。如果一个线程不竞争对象锁,它将留在锁池中。只有当线程再次调用wait()方法时,它才会返回等待池。竞争对象锁的线程将继续执行,直到同步代码块完成,并且它将释放对象锁。此时,锁池中的线程将继续竞争对象锁。
综上所述,所谓唤醒线程的另一种解释是将线程从等待池移到锁池。调用notifyAll后,所有线程都将从等待池移动到锁池,然后参与锁竞争。如果竞争成功,它将继续执行。如果不成功,它将留在锁池中,等待锁被释放后再重新参加比赛。而notify只会唤醒一个线程。
有了这些理论基础,就很容易解释下面这个例子,notify可能会导致死锁,但notifyAll不会。
测试代码
公共类TestNotifyNotifyAll {
私有静态对象obj=new Object();
公共静态void main(String[] args) {
//测试RunnableImplA wait()
线程t1=新线程(新runnable impla(obj));
线程t2=新线程(新runnable impla(obj));
t1 . start();
T2 . start();
//RunnableImplB notify()
Thread t3=新线程(new RunnableImplB(obj));
T3 . start();
////RunnableImplC notifyAll()
//Thread T4=new Thread(new RunnableImplC(obj));
//T4 . start();
}
}
类RunnableImplA实现Runnable {
私有对象obj
public runnable impla(Object obj){
this.obj=obj
}
公共无效运行(){
system . out . println(' runnable impla上运行');
同步(对象){
System.out.println('obj以等待runnable impla ');
尝试{
obj . wait();
} catch (InterruptedException e) {
e . printstacktrace();
}
System.out.println('obj继续在RunnableImplA上运行');
}
}
}
类RunnableImplB实现Runnable {
私有对象obj
public RunnableImplB(Object obj){
this.obj=obj
}
公共无效运行(){
system . out . println(' run on runnable implb ');
System.out.println('睡眠3秒.');
尝试{
thread . sleep(3000);
} catch (InterruptedException e) {
e . printstacktrace();
}
同步(对象){
system . out . println(' notify obj on runnable implb ');
obj . notify();
}
}
}
类RunnableImplC实现Runnable {
私有对象obj
public runnable implc(Object obj){
this.obj=obj
}
公共无效运行(){
system . out . println(' run on runnable implc ');
System.out.println('睡眠3秒.');
尝试{
thread . sleep(3000);
} catch (InterruptedException e) {
e . printstacktrace();
}
同步(对象){
system . out . println(' notify all obj on runnable implc ');
obj . notifyall();
}
}
}
结果:仅调用一次obj.notify(),线程一种网络的名称(传输率可达1.54mbps)级(一种通讯线路的名称)或t2中的一个始终在等待被唤醒,程序不终止
在RunnableImplA上运行
等待RunnableImplA
在RunnableImplA上运行
等待RunnableImplA
在RunnableImplB上运行
睡眠3秒.
在RunnableImplB上通知对象
目标文件继续在RunnableImplA上运行
把t3注掉,启动t4线程。调用obj.notifyAll()方法
公共类TestNotifyNotifyAll {
私有静态对象obj=new Object();
公共静态void main(String[] args) {
//测试RunnableImplA等待()
线程t1=新线程(新runnable impla(obj));
线程t2=新线程(新runnable impla(obj));
t1。start();
T2。start();
////RunnableImplB notify()
//Thread T3=new Thread(new RunnableImplB(obj));
//T3。start();
//RunnableImplC notifyAll()
线程t4=新线程(new RunnableImplC(obj));
T4。start();
}
}
结果:t1、t2线程均可以执行完毕
在RunnableImplA上运行
等待RunnableImplA
在RunnableImplA上运行
等待RunnableImplA
在RunnableImplC上运行
睡眠3秒.
RunnableImplC上的notifyAll对象
目标文件继续在RunnableImplA上运行
目标文件继续在RunnableImplA上运行
到此这篇关于Java 语言(一种计算机语言,尤用于创建网站)语言(一种计算机语言,尤用于创建网站)中通知()和notifyAll()的使用区别的文章就介绍到这了,更多相关Java 语言(一种计算机语言,尤用于创建网站)通知()和notifyAll()内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。