一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語言 - JAVA教程 - 淺談java線程中生產(chǎn)者與消費(fèi)者的問題

淺談java線程中生產(chǎn)者與消費(fèi)者的問題

2020-05-28 13:35jingxian JAVA教程

下面小編就為大家?guī)硪黄獪\談java線程中生產(chǎn)者與消費(fèi)者的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

一、概念

生產(chǎn)者與消費(fèi)者問題是一個金典的多線程協(xié)作的問題.生產(chǎn)者負(fù)責(zé)生產(chǎn)產(chǎn)品,并將產(chǎn)品存放到倉庫;消費(fèi)者從倉庫中獲取產(chǎn)品并消費(fèi)。當(dāng)倉庫滿時(shí),生產(chǎn)者必須停止生產(chǎn),直到倉庫有位置存放產(chǎn)品;當(dāng)倉庫空時(shí),消費(fèi)者必須停止消費(fèi),直到倉庫中有產(chǎn)品。

解決生產(chǎn)者/消費(fèi)者問題主要用到如下幾個技術(shù):1.用線程模擬生產(chǎn)者,在run方法中不斷地往倉庫中存放產(chǎn)品。2.用線程模擬消費(fèi)者,在run方法中不斷地從倉庫中獲取產(chǎn)品。3

 . 倉庫類保存產(chǎn)品,當(dāng)產(chǎn)品數(shù)量為0時(shí),調(diào)用wait方法,使得當(dāng)前消費(fèi)者線程進(jìn)入等待狀態(tài),當(dāng)有新產(chǎn)品存入時(shí),調(diào)用notify方法,喚醒等待的消費(fèi)者線程。當(dāng)倉庫滿時(shí),調(diào)用wait方法,使得當(dāng)前生產(chǎn)者線程進(jìn)入等待狀態(tài),當(dāng)有消費(fèi)者獲取產(chǎn)品時(shí),調(diào)用notify方法,喚醒等待的生產(chǎn)者線程。

二、實(shí)例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
package book.thread.product;
 
public class Consumer extends Thread{
  private Warehouse warehouse;//消費(fèi)者獲取產(chǎn)品的倉庫
  private boolean running = false;//是否需要結(jié)束線程的標(biāo)志位
  public Consumer(Warehouse warehouse,String name){
    super(name);
    this.warehouse = warehouse;
  }
  public void start(){
    this.running = true;
    super.start();
  }
  public void run(){
    Product product;
    try {
      while(running){
        //從倉庫中獲取產(chǎn)品
        product = warehouse.getProduct();
        sleep(500);
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
  //停止消費(fèi)者線程
  public void stopConsumer(){
    synchronized(warehouse){
      this.running = false;
      warehouse.notifyAll();//通知等待倉庫的線程
    }
  }
  //消費(fèi)者線程是否在運(yùn)行
  public boolean isRunning(){
    return running;
  }
}
 
 
 
package book.thread.product;
 
public class Producer extends Thread{
   private Warehouse warehouse;//生產(chǎn)者存儲產(chǎn)品的倉庫
  private static int produceName = 0;//產(chǎn)品的名字
  private boolean running = false;//是否需要結(jié)束線程的標(biāo)志位
 
  public Producer(Warehouse warehouse,String name){
    super(name);
    this.warehouse = warehouse;
  }
  public void start(){
    this.running = true;
    super.start();
  }
  public void run(){
    Product product;
    //生產(chǎn)并存儲產(chǎn)品
    try {
    while(running){
      product = new Product((++produceName)+"");
      this.warehouse.storageProduct(product);
      sleep(300);
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
  //停止生產(chǎn)者線程
  public void stopProducer(){
    synchronized(warehouse){
      this.running = false;
      //通知等待倉庫的線程
      warehouse.notifyAll();
    }
  }
  //生產(chǎn)者線程是否在運(yùn)行
  public boolean isRunning(){
    return running;
  }
}
 
 
 
package book.thread.product;
 
public class Product {
  private String name;//產(chǎn)品名
  public Product(String name){
    this.name = name;
  }
  public String toString(){
    return "Product-"+name;
  }
}
 
 
 
package book.thread.product;
 
//產(chǎn)品的倉庫類,內(nèi)部采用數(shù)組來表示循環(huán)隊(duì)列,以存放產(chǎn)品
public class Warehouse {
  private static int CAPACITY = 11;//倉庫的容量
  private Product[] products;//倉庫里的產(chǎn)品
  //[front,rear]區(qū)間的產(chǎn)品未被消費(fèi)
  private int front = 0;//當(dāng)前倉庫中第一個未被消費(fèi)的產(chǎn)品的下標(biāo)
  private int rear = 0;//倉庫中最后一個未被消費(fèi)的產(chǎn)品下標(biāo)加1
  public Warehouse(){
    this.products = new Product[CAPACITY];
  }
  public Warehouse(int capacity){
    this();
    if(capacity > 0){
      CAPACITY = capacity +1;
      this.products = new Product[CAPACITY];
    }
  }
 
  //從倉庫獲取一個產(chǎn)品
  public Product getProduct() throws InterruptedException{
    synchronized(this){
      boolean consumerRunning = true;//標(biāo)志消費(fèi)者線程是否還在運(yùn)行
      Thread currentThread = Thread.currentThread();//獲取當(dāng)前線程
      if(currentThread instanceof Consumer){
        consumerRunning = ((Consumer)currentThread).isRunning();
      }else{
        return null;//非消費(fèi)者不能獲取產(chǎn)品
      }
      //若消費(fèi)者線程在運(yùn)行中,但倉庫中沒有產(chǎn)品了,則消費(fèi)者線程繼續(xù)等待
      while((front==rear) && consumerRunning){
        wait();
        consumerRunning = ((Consumer)currentThread).isRunning();
      }
      //如果消費(fèi)者線程已經(jīng)停止運(yùn)行,則退出該方法,取消獲取產(chǎn)品
      if(!consumerRunning){
        return null;
      }
      //獲取當(dāng)前未被消費(fèi)的第一個產(chǎn)品
      Product product = products[front];
      System.out.println("Consumer[" + currentThread.getName()+"] getProduct:"+product);
      //將當(dāng)前未被消費(fèi)產(chǎn)品的下標(biāo)后移一位,如果到了數(shù)組末尾,則移動到首部
      front = (front+1+CAPACITY)%CAPACITY;
      System.out.println("倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:"+(rear+CAPACITY-front)%CAPACITY);
      //通知其他等待線程
      notify();
      return product;
    }
  }
  //向倉庫存儲一個產(chǎn)品
  public void storageProduct(Product product) throws InterruptedException{
  synchronized(this){
    boolean producerRunning = true;//標(biāo)志生產(chǎn)者線程是否在運(yùn)行
    Thread currentThread = Thread.currentThread();
    if(currentThread instanceof Producer){
      producerRunning = ((Producer)currentThread).isRunning();
    }else{
      return;
    }
    //如果最后一個未被消費(fèi)的產(chǎn)品與第一個未被消費(fèi)的產(chǎn)品的下標(biāo)緊挨著,則說明沒有存儲空間了。
    //如果沒有存儲空間了,而生產(chǎn)者線程還在運(yùn)行,則生產(chǎn)者線程等待倉庫釋放產(chǎn)品
    while(((rear+1)%CAPACITY == front) && producerRunning){
      wait();
      producerRunning = ((Producer)currentThread).isRunning();
    }
    //如果生產(chǎn)線程已經(jīng)停止運(yùn)行了,則停止產(chǎn)品的存儲
    if(!producerRunning){
      return;
    }
    //保存產(chǎn)品到倉庫
    products[rear] = product;
    System.out.println("Producer[" + Thread.currentThread().getName()+"] storageProduct:" + product);
    //將rear下標(biāo)循環(huán)后移一位
    rear = (rear + 1)%CAPACITY;
    System.out.println("倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:"+(rear + CAPACITY -front)%CAPACITY);
    notify();
    }
  }
}
 
 
 
package book.thread.product;
 
public class TestProduct {
  public static void main(String[] args) {
    Warehouse warehouse = new Warehouse(10);//建立一個倉庫,容量為10
    //建立生產(chǎn)者線程和消費(fèi)者
    Producer producers1 = new Producer(warehouse,"producer-1");
    Producer producers2 = new Producer(warehouse,"producer-2");
    Producer producers3 = new Producer(warehouse,"producer-3");
    Consumer consumer1 = new Consumer(warehouse,"consumer-1");
    Consumer consumer2 = new Consumer(warehouse,"consumer-2");
    Consumer consumer3 = new Consumer(warehouse,"consumer-3");
    Consumer consumer4 = new Consumer(warehouse,"consumer-4");
    //啟動生產(chǎn)者線程和消費(fèi)者線程
    producers1.start();
    producers2.start();
    consumer1.start();
    producers3.start();
    consumer2.start();
    consumer3.start();
    consumer4.start();
    //讓生產(chǎn)者/消費(fèi)者程序運(yùn)行1600ms
    try {
      Thread.sleep(1600);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    //停止消費(fèi)者線程
    producers1.stopProducer();
    consumer1.stopConsumer();
    producers2.stopProducer();
    consumer2.stopConsumer();
    producers3.stopProducer();
    consumer3.stopConsumer();
    consumer4.stopConsumer();
  }
}

輸出結(jié)果:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
Producer[producer-1] storageProduct:Product-1
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:1
Consumer[consumer-2] getProduct:Product-1
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:0
Producer[producer-3] storageProduct:Product-3
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:1
Producer[producer-2] storageProduct:Product-2
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:2
Consumer[consumer-3] getProduct:Product-3
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:1
Consumer[consumer-1] getProduct:Product-2
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:0
Producer[producer-1] storageProduct:Product-4
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:1
Consumer[consumer-4] getProduct:Product-4
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:0
Producer[producer-3] storageProduct:Product-6
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:1
Producer[producer-2] storageProduct:Product-5
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:2
Consumer[consumer-1] getProduct:Product-6
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:1
Consumer[consumer-2] getProduct:Product-5
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:0
Producer[producer-1] storageProduct:Product-7
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:1
Consumer[consumer-3] getProduct:Product-7
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:0
Producer[producer-3] storageProduct:Product-8
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:1
Producer[producer-2] storageProduct:Product-9
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:2
Consumer[consumer-4] getProduct:Product-8
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:1
Producer[producer-1] storageProduct:Product-10
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:2
Producer[producer-3] storageProduct:Product-11
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:3
Producer[producer-2] storageProduct:Product-12
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:4
Consumer[consumer-1] getProduct:Product-9
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:3
Consumer[consumer-2] getProduct:Product-10
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:2
Consumer[consumer-3] getProduct:Product-11
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:1
Producer[producer-3] storageProduct:Product-13
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:2
Producer[producer-1] storageProduct:Product-14
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:3
Producer[producer-2] storageProduct:Product-15
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:4
Consumer[consumer-4] getProduct:Product-12
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:3
Consumer[consumer-1] getProduct:Product-13
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:2
Consumer[consumer-2] getProduct:Product-14
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:1
Producer[producer-1] storageProduct:Product-16
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:2
Producer[producer-3] storageProduct:Product-17
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:3
Producer[producer-2] storageProduct:Product-18
倉庫中還沒有被消費(fèi)的產(chǎn)品數(shù)量:4

分析:在main方法中建立了一個產(chǎn)品倉庫,并未該倉庫關(guān)聯(lián)了3個生產(chǎn)者線程和4個消費(fèi)者線程,啟動這些線程,使生產(chǎn) 者/消費(fèi)者模型運(yùn)作起來,當(dāng)程序運(yùn)行1600ms時(shí),所有的生產(chǎn)者停止生產(chǎn)產(chǎn)品,消費(fèi)者停止消費(fèi)產(chǎn)品。

生產(chǎn)者線程Product在run方法中沒300ms便生產(chǎn)一個產(chǎn)品,并存入倉庫;消費(fèi)者線程Consumer在run方法中沒500ms便從倉庫中取一個產(chǎn)品。

倉庫類Warehouse負(fù)責(zé)存放產(chǎn)品和發(fā)放產(chǎn)品。storageProduct方法負(fù)責(zé)存儲產(chǎn)品,當(dāng)倉庫滿時(shí),當(dāng)前線程進(jìn)入等待狀態(tài),即如果生產(chǎn)者線程A在調(diào)用storageProduct方法以存儲產(chǎn)品時(shí),發(fā)現(xiàn)倉庫已滿,無法存儲時(shí),便會進(jìn)入等待狀態(tài)。當(dāng)存儲產(chǎn)品成功時(shí),調(diào)用notify方法,喚醒等待的消費(fèi)者線程。

getProduct方法負(fù)責(zé)提前產(chǎn)品,當(dāng)倉庫空時(shí),當(dāng)前線程進(jìn)入等待狀態(tài),即如果消費(fèi)者線程B在調(diào)用getProduct方法以獲取產(chǎn)品時(shí),發(fā)現(xiàn)倉庫空了,便會進(jìn)入等待狀態(tài)。當(dāng)提取產(chǎn)品成功時(shí),調(diào)用notify方法,喚醒等待的生產(chǎn)者線程。

以上這篇淺談java線程中生產(chǎn)者與消費(fèi)者的問題就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持服務(wù)器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 人人看人人射 | 色婷婷久久综合中文久久一本` | 高h校花| 貂蝉沦为姓奴小说 | 青青网在线视频 | 韩日视频在线 | 欧美男同互吃gay老头 | 国产精品免费综合一区视频 | 亚洲精品视频免费在线观看 | 五月天中文在线 | 日本色淫 | 刺客女仆| 国产剧情在线播放 | 5g影院天天| 国产精品边做边接电话在线观看 | 美女女女女女女bbbbbb毛片 | 插入肥臀 | 九九九九九九伊人 | 国产精品久久久久久影视 | 99这里只有精品66视频 | 精品国产品香蕉在线观看 | 亚洲2017天堂色无码 | 白发在线视频播放观看免费 | 国产成年人在线观看 | 亚洲国产精品无码中文字幕 | 校园春色偷拍自拍 | 国产男女乱淫真视频全程播放 | 波多野结衣作品在线观看 | 男人猛激烈吃奶gif动态图 | 免费免费啪视频在线观播放 | 国产成人综合一区精品 | 99久久精品免费看国产一区 | 久久亚洲国产成人影院 | 国产第一页在线视频 | 肉大捧一进一出视频免费播放 | 欧美大片一区 | 国产91一区二区在线播放不卡 | 青青国产成人久久91网 | 九九久久国产精品免费热6 九九精品视频一区二区三区 | 久久综合视频网站 | 午夜视频一区二区 |