notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法
- void notify(): 唤醒一个正在等待该对象的线程。
- void notifyAll(): 唤醒所有正在等待该对象的线程。
两者的最大区别在于:
- notifyAll使所有原来在该对象上等待被notify的线程统统退出wait的状态,变成等待该对象上的锁,一旦该对象被解锁,他们就会去竞争。
- notify他只是选择一个wait状态线程进行通知,并使它获得该对象上的锁,但不惊动其他同样在等待被该对象notify的线程们,当第一个线程运行完毕以后释放对象上的锁,此时如果该对象没有再次使用notify语句,即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,继续处在wait状态,直到这个对象发出一个notify或notifyAll,它们等待的是被notify或notifyAll,而不是锁。
多个线程拥有同一个同步对象时,用notifyAll会造成异常的实例
import java.util.ArrayList; import java.util.List; class Widget{} class WidgetMaker extends Thread{ List finishedWidgets = new ArrayList(); public void run(){ try{ while(true){ // 每5s产生对象加入List Thread.sleep(5000); Widget w = new Widget(); Widget i = new Widget(); Widget d = new Widget(); synchronized (finishedWidgets) { finishedWidgets.add(w); finishedWidgets.add(i); finishedWidgets.add(d); // 向List加入3个元素后通知wait对象唤醒 // 如果此处使用notifyAll(),第一个线程得到了锁,而其他线程也从wait状态被唤醒执行remove命令,部分List会出现空元素remove出现异常,notify则只选择当前wait状态线程进行唤醒,并使它获得该对象上的锁,但不惊动其他同样在等待被该对象notify的线程们 finishedWidgets.notify(); } } }catch(InterruptedException e) {} } // 如果List中有就一直返回,直到List为空时wait public Widget waitForWiget() { synchronized (finishedWidgets) { if (finishedWidgets.size() == 0) { try { finishedWidgets.wait(); } catch (InterruptedException e) { } } return (Widget) finishedWidgets.remove(0); } } } public class WidgetUser extends Thread{ private WidgetMaker maker; public WidgetUser(String name,WidgetMaker maker){ super(name); this.maker = maker; } public void run(){ Widget w = maker.waitForWiget(); System.out.println(getName()+"got a widget"); } public static void main(String[] args){ WidgetMaker maker = new WidgetMaker(); maker.start(); new WidgetUser("Lenny", maker).start(); new WidgetUser("Moe", maker).start(); new WidgetUser("Curly", maker).start(); } }
时间: 2024-10-09 16:44:31