纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

Java notify()和notifyAll() Java中notify()和notifyAll()的使用区别

ConstXiong   2021-06-24 我要评论
想了解Java中notify()和notifyAll()的使用区别的相关内容吗ConstXiong在本文为您仔细讲解Java notify()和notifyAll()的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Java,notify(),notifyAll()下面大家一起来学习吧

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

先解释两个概念

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

然后再来说notify和notifyAll的区别

  • 如果线程调用了对象的 wait()方法那么线程便会处于该对象的等待池中等待池中的线程不会去竞争该对象的锁
  • 当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程)被唤醒的的线程便会进入该对象的锁池中锁池中的线程会去竞争该对象锁也就是说调用了notify后只要一个线程会由等待池进入锁池而notifyAll会将该对象等待池内的所有线程移动到锁池中等待锁竞争
  • 优先级高的线程竞争到对象锁的概率大假若某线程没有竞争到该对象锁它还会留在锁池中唯有线程再次调用 wait()方法它才会重新回到等待池中而竞争到对象锁的线程则继续往下执行直到执行完了 synchronized 代码块它会释放掉该对象锁这时锁池中的线程会继续竞争该对象锁

综上所谓唤醒线程另一种解释可以说是将线程由等待池移动到锁池notifyAll调用后会将全部线程由等待池移到锁池然后参与锁的竞争竞争成功则继续执行如果不成功则留在锁池等待锁被释放后再次参与竞争而notify只会唤醒一个线程

有了这些理论基础后面的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


相关文章

猜您喜欢

  • Activity侧滑返回 剖析Android Activity侧滑返回的实现原理

    想了解剖析Android Activity侧滑返回的实现原理的相关内容吗怪兽N在本文为您仔细讲解Activity侧滑返回的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Activity侧滑返回,android,Activity侧滑返回下面大家一起来学习吧..
  • Python绘图turtle库 Python绘图之turtle库的基础语法使用

    想了解Python绘图之turtle库的基础语法使用的相关内容吗简时刻在本文为您仔细讲解Python绘图turtle库的相关知识和一些Code实例欢迎阅读和指正我们先划重点:python绘图turtle库详解,python中turtle库,python中turtle库的用法下面大家一起来学习吧..

网友评论

Copyright 2020 www.gamerfx.net 【游戏天空】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式