Java多線程Producer-Consumer模式我來做你來用

概述

生產(chǎn)者安全地將數(shù)據(jù)交給消費者城菊。當兩者在不同的線程運行時备燃,處理速度會引起問題。生產(chǎn)者和消費者一般都有多個凌唬,也可以只有一個生產(chǎn)者和一個消費者赚爵,稱為Pipe模式。

示例程序

3位蛋糕師傅制作蛋糕法瑟,房子桌子上冀膝,然后3位客人來吃這些蛋糕。
    -  糕點師(MakerThread)制作蛋糕(String)霎挟,并將其放在桌子上
    -  桌子上最多可放置3個蛋糕
    -  如果桌子上已經(jīng)放滿3個蛋糕時糕點師還要放置蛋糕窝剖,必須等到桌子上空出位置
    - 客人(EaterThread)取桌子上的蛋糕吃
    - 客人按蛋糕被放置到桌子上的順序來取蛋糕
    - 當桌子上1個蛋糕都沒有時, 客人若要取蛋糕酥夭,必須等到桌子上放置了蛋糕
Main類
 Main類會創(chuàng)建一個桌子的實例赐纱,并啟動表示蛋糕師和客人的線程授翻。MakerThread和EaterThread的構(gòu)造函數(shù)傳入的數(shù)字只是用來作為隨機數(shù)的種子丁溅,數(shù)值本身并沒有什么特別的意義悍引。
public class Main {
  public static void main(String[] args){
    Table table = new Table(3);     //創(chuàng)建能放三個蛋糕的桌子
    new MakerThread("MakerThread-1", table, 12121).start();
    new MakerThread("MakerThread-2", table, 24242).start();
    new MakerThread("MakerThread-3", table, 36363).start();
    new EaterThread("EaterThread-1", table, 47474).start();
    new EaterThread("EaterThread-2", table, 58585).start();
    new EaterThread("EaterThread-3", table, 69696).start();
  }
}
MakerThread類
import java.util.Random;
public class MakerThread extends Thread {
  private final Random random;
  private final Table table;
  private static int id = 0;          //蛋糕的流水號(所有蛋糕師公用)
  public MakerThread(String name, Table table, long seed){
    super(name);
    this.table = table;
    this.random = new Random(seed);
  }
  public void run() {
    try {
      while (true){
        Thread.sleep(random.nextInt(1000));
        String cake = "[ Cake No." + nextId() + " by " + getName() + "  ]";
         table.put(cake);
      }
    } catch (InterruptedException e){
    }
  }
  private static synchronized int nextId(){
    return id++;
  }
}
EaterThread 類
import java.util.Random;
public class EaterThread extends Thread {
  private final Random random;
  private final Table table;
  public EaterThread(String name, Table table, long seed){
    super(name);
    this.table = table;
    this.random = new Random(seed);
  }
  public void run(){
    try{
      while(true){
        String cake = table.take();
        Thread.sleep(random.nextInt(1000));
      }
    } catch (InterruptedException e){}
  }
}
Table 類
public class Table {
  private final String[] buffer;
  private int tail;
  private int head;
  private int count;
  public Table(int count){
    this.buffer = new String[count];
    this.head = 0;
    this.tail = 0;
    this.count = 0;
  }
  //放置蛋糕
  public synchronized void put(String cake) throws InterruptedException {
    System.out.println(Thread.currentThread().getName() +"  puts " + cake);
    while(count >= buffer.length){
      wait();
    }
    buffer[tail] = cake;
    tail = (tail + 1) % buffer.length;
    count++;
    notifyAll();
  }
  //拿取蛋糕
  public synchronized String take() throws InterruptedException {
    while (count <= 0) {
      wait();
    }
    String cake = buffer[head];
    head = ( head + 1) % buffer.length;
    count--;
    notifyAll();
    System.out.println(Thread.currentThread().getName() + " takes " + cake;
    return cake
  }
}
put方法解讀
  • throws InterruptedException
    put方法被聲明為可能拋出異常InterruptedException異常的方法信殊。當看到throwsInterruptedException時, 我們可以理解為“該方法可以取消”邪媳。
  • Guarded Suspension模式
    put方法升酣,使用while條件表達的守護條件幻工,即“當前桌子上放置的蛋糕數(shù)小于能夠放置的最大數(shù)”巫延,也就是“還有可以放置的位置”效五,作為put方法的守護條件。
  • tail 和 count 的更新
    tail表示下次放置蛋糕的位置炉峰, buffer[tail] = cake; 放置后畏妖,tail要加1就可以了 tail = (tail + 1) % buffer.length;
    桌子上的蛋糕增多了,所以count的值也需要加1疼阔。
  • notifyAll
    上面已經(jīng)把蛋糕放到桌子上戒劫,由于桌子的狀態(tài)發(fā)生了變化,所以要執(zhí)行notifyAll婆廊,喚醒所有正在wait的線程迅细。
take方法解讀
  • throws InterruptedException
    說明此方法時可以取消的方法
  • Guarded Suspension 模式
    守護條件是“當前桌子上至少有一個蛋糕”。
  • head 和 count的更新
    head 表示下次取蛋糕的位置否彩,蛋糕取走之后疯攒,head也要前進。head = (head + 1) % buffer.length;
    桌子上的蛋糕取走了一個列荔, 所以count的值也需要減一敬尺。
  • notifyAll
    通過上面的處理,蛋糕被取走了贴浙,桌面就發(fā)生了變化砂吞,所以要執(zhí)行notifyAll,喚醒所有正在wait的線程崎溃。

Producer-Consumer 模式的角色

  • Data 由Producer角色生成蜻直,供Consumer角色使用。在示例程序中袁串,由String類(蛋糕)扮演概而。
  • Producer 此角色生成Data角色,并將其傳遞給Channel角色囱修。在示例中赎瑰,由MakerThread扮演。
  • Consumer 消費者角色從Channel角色獲取Data角色破镰。在示例程序中餐曼,由EaterThread扮演此角色
  • Channel 通道角色用于承擔傳遞Data角色的中轉(zhuǎn)站、通道的任務(wù)鲜漩。在示例程序中由Table扮演源譬。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市孕似,隨后出現(xiàn)的幾起案子踩娘,更是在濱河造成了極大的恐慌,老刑警劉巖喉祭,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件霸饲,死亡現(xiàn)場離奇詭異,居然都是意外死亡臂拓,警方通過查閱死者的電腦和手機厚脉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胶惰,“玉大人傻工,你說我怎么就攤上這事》踔停” “怎么了中捆?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長坊饶。 經(jīng)常有香客問我泄伪,道長,這世上最難降的妖魔是什么匿级? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任蟋滴,我火速辦了婚禮染厅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘津函。我一直安慰自己肖粮,他們只是感情好,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布尔苦。 她就那樣靜靜地躺著涩馆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪允坚。 梳的紋絲不亂的頭發(fā)上魂那,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天,我揣著相機與錄音稠项,去河邊找鬼涯雅。 笑死,一個胖子當著我的面吹牛皿渗,可吹牛的內(nèi)容都是我干的斩芭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼乐疆,長吁一口氣:“原來是場噩夢啊……” “哼划乖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起挤土,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤琴庵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后仰美,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體迷殿,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年咖杂,在試婚紗的時候發(fā)現(xiàn)自己被綠了庆寺。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡诉字,死狀恐怖懦尝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情壤圃,我是刑警寧澤陵霉,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站伍绳,受9級特大地震影響踊挠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜冲杀,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一效床、第九天 我趴在偏房一處隱蔽的房頂上張望睹酌。 院中可真熱鬧,春花似錦扁凛、人聲如沸忍疾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至甥绿,卻和暖如春字币,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背共缕。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工洗出, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人图谷。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓翩活,卻偏偏與公主長得像,于是被迫代替她去往敵國和親便贵。 傳聞我的和親對象是個殘疾皇子菠镇,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 本文是我自己在秋招復(fù)習時的讀書筆記,整理的知識點承璃,也是為了防止忘記利耍,尊重勞動成果,轉(zhuǎn)載注明出處哦盔粹!如果你也喜歡隘梨,那...
    波波波先森閱讀 11,242評論 4 56
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)舷嗡,斷路器轴猎,智...
    卡卡羅2017閱讀 134,628評論 18 139
  • 現(xiàn)狀:不經(jīng)常讀書,偶爾會看进萄,但沒有堅持看完整本書捻脖。 66 天達成的期望情況和狀態(tài):培養(yǎng)出每天在晚上看書的習慣,做到...
    forever微微一笑閱讀 239評論 0 0
  • 只要認真的為自己活過垮斯,只要為生命中重要的人郎仆,努力奮斗過,這樣的人生才算是完美 你的態(tài)度 ...
    Gigi_d66b閱讀 203評論 0 1
  • 一種“陌生人”是天天見面卻形同陌路的熟人兜蠕,比如同一個單位的同事扰肌,你知道她姓啥名啥,大約多大年齡熊杨,人品如何...
    迎恩閱讀 331評論 2 1