溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java多線程中消費者與生產(chǎn)者的關(guān)系是什么

發(fā)布時間:2021-11-20 14:21:33 來源:億速云 閱讀:147 作者:小新 欄目:編程語言

這篇文章將為大家詳細(xì)講解有關(guān)Java多線程中消費者與生產(chǎn)者的關(guān)系是什么,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

  多線程:CPU中各種任務(wù)在交替執(zhí)行過程中,被稱為多線程處理。其中,每個任務(wù)的一次動態(tài)執(zhí)行過程被稱為進程。進程執(zhí)行過程中的暫停被稱為中斷。進程通過中斷被分解成若干段,每一段被稱為一個線程。

  在消費者與生產(chǎn)者中,我們設(shè)定單個生產(chǎn)者的每次活動是饅頭 +1;單個消費者每次進行的是饅頭 -1;然后消費者和生產(chǎn)者的活動時間不確定,同時生產(chǎn)者和消費者的數(shù)量不確定,該經(jīng)典問題我們使用多線程實現(xiàn):

  我們首先確定實物,即生產(chǎn)者的每次生成的物品,在這里我們使用饅頭代替。在WoTou的類中,我們可以看到有著自己獨特的屬性,即饅頭的 id,我們可以在控制臺清晰的看到饅頭的生產(chǎn)和消費過程,具體實現(xiàn)代碼如下:

  class WoTou{ //饅頭,生產(chǎn)者生產(chǎn)的饅頭

  int id;

  WoTou(int id){

  this.id = id;

  }

  public String toString(){

  return "WoTou:"+ id;

  }

  }

  我們需要確定饅頭的存儲容器,即在消費和生產(chǎn)發(fā)生的時候,我們需要在什么地方進行判斷,饅頭是否耗盡,或者饅頭是否滿溢。每次活動都是相當(dāng)于在棧中取東西和放東西,所以我們根據(jù)棧的特性為:先進后出 原則。

  class SyncStack {//籃子容器,放饅頭用的

  int index = 0;

  WoTou[] arrWT = new WoTou[6];

  }

  在籃子容器中我們簡單定義棧的最大容量為6,我們之后設(shè)定生產(chǎn)者的類,定義為producer類。我們知道producer有著一些自己的獨特屬性,即往籃子SyncStack中放WoTou,每次進行饅頭+1操作,還有生產(chǎn)者的操作Time間隔,是隔10毫秒還是5毫秒,我們使得producer類實現(xiàn)其Runnerable接口,調(diào)用線程的run()方法,具體代碼如下:

  class Producer implements Runnable{ //生產(chǎn)者

  SyncStack ss= null;

  Producer(SyncStack ss){

  this.ss = ss;

  }

  public void run(){

  for(int i=0;i<20;i++){

  WoTou wt = new WoTou(i);

  ss.push(wt);

  System.out.println("生產(chǎn)者:"+wt);

  try {

  Thread.sleep((int)(Math.random()*1000));

  } catch (InterruptedException e) {

  // TODO: handle exception

  e.printStackTrace();

  }

  }

  }

  }

  生產(chǎn)者在往棧中添加數(shù)據(jù)的時候,我們使用push方法進行插入。同時定義插入的饅頭數(shù)量,這里的數(shù)量并不是籃子的饅頭數(shù)量?;@子里邊雖然只能一次性裝6個饅頭,但是消費者是同時間進行操作的,所以籃子的饅頭數(shù)量在消費之后,生產(chǎn)者繼續(xù)進行生產(chǎn),一直到生產(chǎn)20個饅頭為止。

  消費者我們這里定義為Consumer類,消費者和生產(chǎn)者有一定的相似性,但是我們需要消費在籃子中拿的過程,我們使用pop操作,同時定義消費數(shù)量,以及操作間隔,這里都是使用線程的sleep(時間)方法, 代碼如下:

  class Consumer implements Runnable{ //消費者

  SyncStack ss= null;

  Consumer(SyncStack ss){

  this.ss = ss;

  }

  public void run(){

  for(int i=0;i<20;i++){

  WoTou wt = ss.pop();

  System.out.println("消費量:"+wt);

  try {

  Thread.sleep((int)(Math.random()*1000));

  } catch (InterruptedException e) {

  // TODO: handle exception

  e.printStackTrace();

  }

  }

  }

  }

  最后我們考慮在籃子中,假如容量已滿,即生產(chǎn)者生產(chǎn)過多,消費的太慢,那么生產(chǎn)者需要休息;同樣的消費過快,容器數(shù)量為0,消費者開始休息。我們在兩種情況發(fā)生的時候,需要設(shè)置兩種方法,在極限情況發(fā)生的時候,進行判斷。簡單實現(xiàn)代碼如下:

  public synchronized void push(WoTou wt){ //往籃子中放饅頭

  while(index == arrWT.length){

  try {

  this.wait();

  } catch (InterruptedException e) {

  // TODO: handle exception

  e.printStackTrace();

  }

  }

  this.notify();

  arrWT[index] = wt;

  index++;

  }鄭州人流多少錢 http://mobile.sgyy029.com/

  我們需要確定是我們在生產(chǎn)者進行活動的時候,不能受到其他線程的影響,即我們需要保持在某一時刻只有一個線程進行操作,這種情況我們需要使用線程的一個synchronized方法。這個方法稱為死鎖,鎖定當(dāng)前方法體執(zhí)行的過程中,保持其獨立性。即在方法體的前面使用synchronized關(guān)鍵字修飾。

  從籃子中取出饅頭的操作類似于生產(chǎn)者,實現(xiàn)代碼如下:

  public synchronized WoTou pop(){ //從籃子中取饅頭

  while(index == 0){

  try {

  this.wait();

  } catch (InterruptedException e) {

  // TODO: handle exception

  e.printStackTrace();

  }

  }

  this.notify();

  index--;

  return arrWT[index];

  }

  我們會發(fā)現(xiàn)在上面兩種動作中,考慮到一個問題,即數(shù)量到極限之后,我們的動作停止了。生產(chǎn)者在籃子容量到達6時,動作停止;消費者在籃子數(shù)量到0后,停止行為。我們這時候開始使用線程的notify方法,喚醒休眠的線程,因為線程使用了wait方法,我們可以喚醒之后,在進行各自的行為。因此籃子SynStack類中詳細(xì)代碼為:

  class SyncStack {//籃子容器,放饅頭用的

  int index = 0;

  WoTou[] arrWT = new WoTou[6];

  public synchronized void push(WoTou wt){ //往籃子中放饅頭

  while(index == arrWT.length){

  try {

  this.wait(); //線程等待

  } catch (InterruptedException e) {

  // TODO: handle exception

  e.printStackTrace();

  }

  }

  this.notify(); //喚醒wait的線程

  arrWT[index] = wt;

  index++;

  }

  public synchronized WoTou pop(){ //從籃子中取饅頭

  while(index == 0){

  try {

  this.wait();

  } catch (InterruptedException e) {

  // TODO: handle exception

  e.printStackTrace();

  }

  }

  this.notify();

  index--;

  return arrWT[index];

  }

  }

  我們可以修改生產(chǎn)者和消費者的數(shù)量和操作間隔,不一定生產(chǎn)+1同時消費-1。我們可以根據(jù)修改進行更改代碼,上面的運行在控制臺數(shù)據(jù)

關(guān)于“Java多線程中消費者與生產(chǎn)者的關(guān)系是什么”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI