wait(),notify()和notifyAll()都是Java基類java.lang.Object的方法。 通俗解釋wait():在當前線程等待其它線程喚醒。notify(): 喚醒一個線程正在等待這個對象的監視器。notifyAll(): 喚醒在這個對象監視器上等待的所有線程。這三個方法,都是
wait(),notify()和notifyAll()都是Java基類java.lang.Object的方法。
通俗解釋
wait():在當前線程等待其它線程喚醒。
notify(): 喚醒一個線程正在等待這個對象的監視器。
notifyAll(): 喚醒在這個對象監視器上等待的所有線程。
這三個方法,都是Java語言提供的實現線程間阻塞(Blocking)和控制進程內調度(inter-process communication)的底層機制。
下麵通過一個生產者/消費者的例子來講解這三個方法的使用
/** * 消費者 * Created by Wiki on 16/1/28. */ public class Customer implements Runnable { private String name; private Channel channel; public Customer(String name, Channel channel) { this.name = name; this.channel = channel; } @Override public void run() { while (true) { Good good = channel.get(); if (good != null) { System.out.println(name + " 獲得商品:" + good.getName()); } else { synchronized (channel) { try { System.out.println(name + " 進入等待"); channel.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
/** * 生產者 * Created by Wiki on 16/1/28. */ public class Producer implements Runnable { private static volatile int goodNumber = 0; private String name; private Channel channel; public Producer(String name, Channel channel) { this.name = name; this.channel = channel; } @Override public void run() { while (true) { int sleep = new Random().nextInt(2000); try { Thread.sleep(sleep); } catch (InterruptedException e) { e.printStackTrace(); } Good good = new Good("商品-編號" + (++goodNumber)); System.out.println(name + " 生產商品:" + good.getName()); channel.put(good); } } }
/** * 商品 * Created by Wiki on 16/1/28. */ public class Good { private String name; public Good(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
/** * 消費通道 * Created by Wiki on 16/1/28. */ public class Channel { private Queue<Good> goodList = new LinkedList<>(); public synchronized Good get() { if (goodList.size() == 0) { return null; } Good good = goodList.remove(); return good; } public synchronized void put(Good good) { goodList.add(good); // notifyAll(); notify(); } }
public class Main { public static void main(String[] args) { Channel channel = new Channel(); new Thread(new Producer("生產者1", channel)).start(); new Thread(new Producer("生產者2", channel)).start(); new Thread(new Producer("生產者2", channel)).start(); new Thread(new Customer("消費者1", channel)).start(); new Thread(new Customer("消費者2", channel)).start(); new Thread(new Customer("消費者3", channel)).start(); } }
運行結果分析一(notify):
每次生產一個商品調用notify時,都只喚醒一個消費者進行消費,喚醒原則是從等待時間最長的開始。
消費者1 進入等待
消費者2 進入等待
消費者3 進入等待
生產者1 生產商品:商品-編號1
消費者1 獲得商品:商品-編號1
消費者1 進入等待
生產者2 生產商品:商品-編號2
消費者2 獲得商品:商品-編號2
消費者2 進入等待
生產者2 生產商品:商品-編號3
消費者3 獲得商品:商品-編號3
消費者3 進入等待
生產者1 生產商品:商品-編號4
消費者1 獲得商品:商品-編號4
消費者1 進入等待
生產者1 生產商品:商品-編號5
消費者2 獲得商品:商品-編號5
消費者2 進入等待
...
運行結果分析二(把notify改成notifyAll):
每生產一件商品時調用notifyAll,都會把所有的消費者喚醒。
消費者1 進入等待
消費者3 進入等待
消費者2 進入等待
生產者2 生產商品:商品-編號1
消費者3 進入等待
消費者2 獲得商品:商品-編號1
消費者1 進入等待
消費者2 進入等待
生產者2 生產商品:商品-編號2
消費者2 獲得商品:商品-編號2
消費者1 進入等待
消費者3 進入等待
消費者2 進入等待
生產者2 生產商品:商品-編號3
消費者2 獲得商品:商品-編號3
...
來源:http://www.taoweiji.cn/index.php/archives/112