一、線程通訊的必要性java
多線程不只共享資源,並且相互牽制向前運行。多線程
二、線程通訊的方法(都是在Object中定義)app
3個方法:dom
1) wait() 可運行轉入阻塞狀態,放鎖測試
2) notify() 阻塞轉入可運行狀態,得到鎖this
3) notifyAll() 全部調用wait方法而被掛起的線程從新啓動,有個條件:wait與notifyAll必須是屬於同一個對象spa
必須在同步方法或同步代碼塊中使用線程
三、共享資源類(倉庫)code
注:共享資源(產品),牽制信息(產品有無)對象
package com.ljb.app.communication; /** * 共享資源類 * @author LJB * @version 2015年3月11日 */ public class ShareData { // 產品 private char c; // 牽制信息(產品有無,開始時倉庫中沒有產品) private boolean isProduced = false; /* * 放產品(生產產品) */ public synchronized void putShareChar (char c) { // 若是消費者尚未消費或者倉庫中有產品,則生產者等待 if (isProduced) { System.out.println("消費者還未消費,所以生產者中止生產。"); try { wait();// 生產者等待 } catch (InterruptedException e) { e.printStackTrace(); } } // 倉庫中放入生產的產品 this.c = c; // 改變信號量(有產品) isProduced = true; // 通知消費者消費 notify(); System.out.println("生產者生產了產品" + c + ",通知消費者消費..."); } /* * 取產品(消費產品) */ public synchronized char getShareChar () { // 若是生產者還未生產或者倉庫中沒有產品,則消費者等待 if (!isProduced) { System.out.println("生產者還未生產,所以消費者中止消費。"); try { wait();// 消費者等待 } catch (InterruptedException e) { e.printStackTrace(); } } // 改變信號量(沒有產品或者消費了該產品) isProduced = false; // 通知生產者生產 notify(); System.out.println("消費者消費了產品" + c + ",通知生產者生產..."); return this.c; } }
四、生產者線程
package com.ljb.app.communication; /** * 生產者線程,每隔一段時間生產一個產品 * @author LJB * @version 2015年3月11日 */ public class Producer extends Thread{ // 共享資源對象 private ShareData s; // 有參構造方法 public Producer (ShareData s) { this.s = s; } public void run () { for (char ch = 'A' ; ch <= 'D' ; ch++) { try { Thread.sleep((int)(Math.random()*3000)); } catch (InterruptedException e) { e.printStackTrace(); } s.putShareChar(ch);// 將產品放入倉庫 } } }
五、消費者線程
package com.ljb.app.communication; /** * 消費者線程 * @author LJB * @version 2015年3月11日 */ public class Consumer extends Thread{ // 共享資源 private ShareData s; // 構造方法 public Consumer (ShareData s) { this.s = s; } public void run () { char ch; do { try { Thread.sleep((int)(Math.random()*3000)); } catch (InterruptedException e) { e.printStackTrace(); } ch = s.getShareChar();// 從倉庫中取出產品 } while (ch != 'D'); } }
六、測試類
package com.ljb.app.communication; /** * 測試類 * @author LJB * @version 2015年3月11日 */ public class Test { /** * @param args */ public static void main(String[] args) { ShareData s = new ShareData(); Thread consumer = new Consumer(s); consumer.start(); Thread producer = new Producer(s); producer.start(); } }
運行結果:
生產者還未生產,所以消費者中止消費。生產者生產了產品A,通知消費者消費...消費者消費了產品A,通知生產者生產...生產者生產了產品B,通知消費者消費...消費者消費了產品B,通知生產者生產...生產者生產了產品C,通知消費者消費...消費者消費了產品C,通知生產者生產...生產者生產了產品D,通知消費者消費...消費者消費了產品D,通知生產者生產...