Java 多執行緒學習(執行緒通訊——消費者和生產者)
執行緒通訊
- 假設倉庫中只能存放一件產品,生產者將生產出來的產品放入倉庫,消費者將倉庫中的產品取走消費。
- 如果倉庫中沒有產品,則生產者將產品放入倉庫,否則停止生產並等待,知道倉庫中的產品被消費者取走為止。
- 如果倉庫中放有產品,則消費者可以將產品取走消費,否則停止消費並等待,知道倉庫中再次放入產品為止。
這是一個執行緒同步問題,生產者和消費者共享一個資源,並且生產者和消費者之間相互依賴,互為條件
在生產者消費者問題中,僅有synchronized是不夠的
- synchronized 可阻止併發更新同一個共享資源,實現了同步。
- synchronized 不能用來實現不同執行緒之間的訊息傳遞(通訊)。
Java提供了幾個方法解決執行緒之間的通訊問題:
- wait() 表示執行緒一直等待,直到其他執行緒通知,與sleep不同,會釋放鎖。
- wait(long timout) 指定等待的毫秒數
- notify() 喚醒一個處於等待狀態的執行緒
- notifyAll() 喚醒同一個物件上所有呼叫wait() 方法的執行緒,優先順序別高的執行緒優先排程。
注意:均是Object類的方法,都只能在同步方法或者同步程式碼塊中使用,否則會丟擲異常IllegalMonitorStateException
1. 解決方式——緩衝區
生產者將生產好的資料放入緩衝區,消費者從緩衝區拿出資料。
程式碼:
package com.mango.gaoji;
// 測試:生產者消費者模型--> 利用緩衝區解決:管程法
// 生產者、消費者、產品、緩衝區
public class TestPC {
public static void main(String[] args) {
Syncontanier contanier = new Syncontanier();
new Productor(contanier).start();
new Consumer(contanier).start();
}
}
// 生產者
class Productor extends Thread{
Syncontanier contanier;
public Productor(Syncontanier contanier) {
this.contanier = contanier;
}
// 生產
@Override
public void run() {
for (int i = 1; i < 100; i++) {
contanier.push(new Chicken(i));
System.out.println("生產了第"+i+"只雞");
}
}
}
// 消費者
class Consumer extends Thread{
Syncontanier contanier;
public Consumer(Syncontanier contanier) {
this.contanier = contanier;
}
// 消費
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消費了第"+contanier.pop().id+"只雞");
}
}
}
// 產品
class Chicken{
int id; // 產品編號
public Chicken(int id) {
this.id = id;
}
}
// 緩衝區
class Syncontanier{
// 需要一個容器大小
Chicken[] chickens =new Chicken[10];
//容器計數器
int count = 0;
// 生產者放入產品
public synchronized void push(Chicken chicken){
// 如果容器滿了就需要等待消費者消費
if(count == chickens.length){
// 通知消費者消費,生產者等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 如果沒有滿,我們就需要丟去產品
chickens[count] = chicken;
count++;
// 可以通知消費者消費了
this.notifyAll();
}
// 消費者消費產品
public synchronized Chicken pop(){
// 判斷能否消費
if(count == 0){
// 等待生產者生產,消費者等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 如果可以消費
count--;
Chicken chicken = chickens[count];
//通知生產者生產
this.notifyAll();
return chicken;
}
}
2. 解決方式——訊號燈
標誌位解決。
程式碼:
其中flag作為標誌位
package com.mango.gaoji;
// 測試生產者消費者問題2:訊號燈法,標誌位解決
public class TestPC2 {
public static void main(String[] args) {
TV tv = new TV();
new Player(tv).start();
new Watcher(tv).start();
}
}
// 生產者——->演員
class Player extends Thread{
TV tv;
public Player(TV tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if(i%2 == 0){
this.tv.player("播放中");
}else{
this.tv.player("抖音");
}
}
}
}
// 消費者-->觀眾
class Watcher extends Thread{
TV tv;
public Watcher(TV tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
this.tv.watch();
}
}
}
// 產品--> 節目
class TV {
// 演員表演,演員等待 T
// 觀眾觀看,演員等待 F
String voice; // 表演節目
boolean flag = true;
// 表演
public synchronized void player(String voice){
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("演員表演了:"+voice);
// 通知觀眾觀看
this.notifyAll(); // 通知喚醒
this.voice = voice;
this.flag = !this.flag;
}
// 觀眾看
public synchronized void watch(){
if (flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("觀眾觀看了:"+voice);
//通知演員表演
this.notifyAll();
this.flag = !this.flag;
}
}
相關文章
- java多執行緒:執行緒間通訊——生產者消費者模型Java執行緒模型
- Java多執行緒——生產者消費者示例Java執行緒
- C#多執行緒學習(三) 生產者和消費者C#執行緒
- Java 多執行緒(Java.Thread)------ 執行緒協作(生產者消費者模式)Java執行緒thread模式
- python執行緒通訊與生產者消費者模式Python執行緒模式
- Java 多執行緒基礎(十二)生產者與消費者Java執行緒
- Java多執行緒——消費者與生產者的關係Java執行緒
- python多執行緒+生產者和消費者模型+queue使用Python執行緒模型
- Java多執行緒學習——執行緒通訊Java執行緒
- Python-多執行緒及生產者與消費者Python執行緒
- python中多執行緒消費者生產者問題Python執行緒
- 生產者消費者模式--java多執行緒同步方法的應用模式Java執行緒
- java學習回顧---生產者與消費者問題以及多執行緒補充Java執行緒
- Java多執行緒學習(3)執行緒同步與執行緒通訊Java執行緒
- python 多執行緒實現生產者與消費者模型Python執行緒模型
- 使用Python佇列和多執行緒實現生產者消費者Python佇列執行緒
- java多執行緒之消費生產模型Java執行緒模型
- Java多執行緒-執行緒通訊Java執行緒
- 多執行緒併發如何高效實現生產者/消費者?執行緒
- Thinking in Java---執行緒通訊+三種方式實現生產者消費者問題ThinkingJava執行緒
- java 執行緒池、多執行緒併發實戰(生產者消費者模型 1 vs 10) 附案例原始碼Java執行緒模型原始碼
- Java多執行緒消費訊息Java執行緒
- Java多執行緒程式設計(同步、死鎖、生產消費者問題)Java執行緒程式設計
- 多執行緒Demo學習(執行緒的同步,簡單的執行緒通訊)執行緒
- java多執行緒5:執行緒間的通訊Java執行緒
- 執行緒間的協作(2)——生產者與消費者模式執行緒模式
- Java多執行緒學習(2)執行緒控制Java執行緒
- 從一次生產消費者的bug看看執行緒池如何增加執行緒執行緒
- java執行緒之守護執行緒和使用者執行緒Java執行緒
- 母雞下蛋例項:多執行緒通訊生產者和消費者wait/notify和condition/await/signal條件佇列執行緒AI佇列
- Java多執行緒學習(五)執行緒間通訊知識點補充Java執行緒
- Java多執行緒學習(一)Java多執行緒入門Java執行緒
- #大學#Java多執行緒學習02(執行緒同步)Java執行緒
- Java多執行緒學習Java執行緒
- Java多執行緒學習(1)建立執行緒與執行緒的生命週期Java執行緒
- Java執行緒通訊Java執行緒
- java多執行緒間的通訊Java執行緒
- 多執行緒之間通訊及執行緒池執行緒