線程通訊(生產者與消費者問題)

一、線程通訊的必要性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,通知生產者生產...

相關文章
相關標籤/搜索