notify与notifyAll的区别
程序员文章站
2022-07-12 19:33:12
...
最近在多线程编程中用到了wait(),随之即面临notify与notifyAll的选择、本人代码中使用两者皆可,查看两者的定义后、发现两者的选择还是很讲究的。
所有处于wait状态的线程,需要使用notify或者notifyAll才能被唤醒、重新被唤醒进入锁的争夺队列。notify即随机唤醒等待中的一条线程;notifyAll即唤醒全部处于等待中的线程。
两者的使用上都存在缺陷,使用notify时、容易导致死锁,而使用notifyAll时容易导致资源竞争使用的异常。所以两者的使用得根据实际情况选择、并没有说普遍的说法。下面分别提供两者使用出错的例子供参考:
使用notify出现死锁:
public class NotifyTest { public static void main(String[] args) { final OutTurn ot = new OutTurn(); for(int i=0; i<30; i++) { new Thread(new Runnable() { public void run() { ot.isSub(); } }).start(); } try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } for(int i=0; i<30; i++) { new Thread(new Runnable() { public void run() { ot.isNotSub(); } }).start(); } System.out.println("Thread cread complate..."); } }
public class OutTurn { private boolean isSub = true; private int count = 0; private int threadCount = 0; public synchronized void isSub() { System.out.println(threadCount++); try { while(!isSub) { System.out.println(Thread.currentThread().getName() + "- sub --- wait --" + count); this.wait(); } System.out.println(Thread.currentThread().getName() + "- sub --- " + count); isSub = false; this.notify();\\采用notifyAll即不会死锁 } catch (Exception e) { e.printStackTrace(); } count++; } public synchronized void isNotSub() { System.out.println(threadCount++); try { while(isSub) { System.out.println(Thread.currentThread().getName() + "- Not --- wait ---" + count); this.wait(); } System.out.println(Thread.currentThread().getName() + "- Not --- " + count); isSub = true; this.notify(); } catch (Exception e) { e.printStackTrace(); } count++; } }
使用notifyAll出现异常:
package notify; import java.util.ArrayList; import java.util.List; public class IntegerMaker implements Runnable { List<Integer> container = new ArrayList<Integer>(); Integer i = 1; @Override public void run() { try { while(true) { Thread.sleep(5000); Integer a = i++; synchronized(container) { container.add(a); container.notify();//notifyAll将出现异常 } } } catch (InterruptedException e) { e.printStackTrace(); } } public Integer waitFor() { synchronized(container) { System.out.println("size"); try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } if(container.size() == 0) { try { container.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("size: " + container.size()); return container.remove(0); } } }
package notify; public class IntegerUser implements Runnable { private IntegerMaker maker; private String name; public IntegerUser(IntegerMaker maker, String name) { this.maker = maker; this.name = name; } public void run() { Integer a = maker.waitFor(); System.out.println(this.name + ":get:" + a); } public static void main(String[] args) { IntegerMaker temp = new IntegerMaker(); Thread maker = new Thread(temp); maker.start(); new Thread(new IntegerUser(temp, "xiaoge1"), "xiaoge1").start(); new Thread(new IntegerUser(temp, "xiaoge2"), "xiaoge2").start(); new Thread(new IntegerUser(temp, "xiaoge3"), "xiaoge3").start(); } }
因此两者的选择必须根据实际情况做具体的分析、然后决定应该唤醒一个还是全部。
上一篇: java 生产者消费者例子
下一篇: OpenNMS数据采集配置
推荐阅读
-
node全局变量__dirname与__filename的区别
-
电子商务与网络营销的区别和关系
-
java与c语言的区别有哪些(全面分析这3个基本区别)
-
having的用法以及与where区别介绍
-
asp.net getRemoteAddr()与 getRemoteHost()的区别
-
PHP中new static()与new self()的区别异同分析
-
实例详解Matlab 与 Python 的区别
-
JQuery中window.onload函数与$(document).ready()的区别实例讲解
-
jquery中html、val与text三者属性取值的联系与区别介绍
-
惠普hp8470p和HP8470W哪款好?8470p与8470w的区别介绍