java-多執行緒管程法,信號燈法
1.管程法:
生產者:負責生產資料的模塊(可能是方法,物件,執行緒,行程)
消費者:負責處理資料的模塊(可能是方法,物件,執行緒,行程)
緩沖區:消費者不能直接使用生產者的資料,他們之間有個緩沖區,生產者將生產好的資料放入緩沖區,消費者從緩沖區拿出資料
思路:
1.首先有一個生產者,消費者、生產者只顧生產,消費者只管消費
2.利用了一個緩沖區,緩沖了一個10個大小的陣列
3.有個方法叫放入產品,產品丟進來的時候,我們判斷一下緩沖區有沒有滿,如果滿了的話,生產者就要等待了,
如果沒有滿,就將產品放進去,放進去之后有產品了,趕緊通知消費者消費
4.消費者就判斷下能不能消費呢,有沒有東西,有東西的話,我就可以直接消費,消費完了,就趕緊通知生產者生產,
如果沒有東西呢,消費者就等待,等待生產者去通知他,生產者通知了,他就可以解除等待了,所以在這一塊存在我們的wait()和notify(),
這里的wait()和notify()都是Object提供的:
wait()導致當前執行緒等待,直到另一個執行緒呼叫該物件的notify()或notifyAll()方法,
notify()喚醒正在等待物件監視器的單個執行緒,
一旦加了wait()之后同樣是進入了阻塞狀態,但是這個阻塞和之前的sleep()不一樣,它會釋放鎖,被wait()的執行緒可以把這個鎖交給其他執行緒去用,否則這個資源就一直被其持有了,
思路有了那么就開始代碼部分了:
(1)創建生產者
// 生產者
class Productor extends Thread{
SynContainer container;
public Productor(SynContainer container){
this.container = container;
}
// 生產
@Override
public void run() {
for (int i = 0; i < 100; i++) {
container.push(new Bug(i));
System.out.println("生產了"+i+"個bug");
}
}
}
(2)創建消滅者
// 消滅bug者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container){
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消滅了-->"+container.pop().id+"個bug");
}
}
}
(3)創建bug區(產品區)
// bug產品
class Bug{
int id;// bug編號
public Bug(int id){
this.id = id;
}
}
(4)創建同步代碼塊(緩沖區)
// 緩沖區
class SynContainer{
// 需要一個容器大小
Bug[] bugs = new Bug[10];
// 容器計算器
int count = 0;
// 生產者放入bug
public synchronized void push(Bug bug){
// 如果容器滿了,就需要等待消滅bug
if(count==bugs.length){
// 通知消滅bug者消滅,生產bug等待
try {
//導致當前執行緒等待,直到另一個執行緒呼叫該物件的 notify()方法或 notifyAll()方法,
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 如果沒有滿,我們就需要繼續生產bug
bugs[count] = bug;
count++;
// 可以通知消滅者消滅了
this.notifyAll();
// notifyAll喚醒正在等待物件監視器的所有執行緒,
}
// 消滅者消滅bug
public synchronized Bug pop(){
// 判斷能否消滅
if (count == 0){
// 等待生產者生產,消滅者等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 如果可以消滅
count--;
Bug bug = bugs[count];
// 消滅完了,通知生產者生產
return bug;
}
}
保證容器中沒有產品的時候生產產品,不能消費;容器中產品滿了的時候,不能再去生產產品
(5)創建測驗類
public class Test {
public static void main(String[] args) {
SynContainer container = new SynContainer();
new Productor(container).start();
new Consumer(container).start();
}
}
(6)測驗

很完美的把全部bug都消滅了
2.信號燈法:
先來理解下信號燈法是什么意思:來判斷一個標志位flag,如果為true,就讓他等待、如果為false,就讓他去通知另外一個人、把兩人銜接起來,就像咱們的信號燈紅燈停,綠燈行,通過這樣一個判斷方式,只要來判斷什么瑞后讓他等待,什么時候將他喚醒就ok,
話不多說直接上代碼^^
package com.macro.mall.bo;
//測驗生產者消費者問題2:信號燈法,通過標志位解決
public class Test {
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.play("什么是快樂星球");
} else {
this.tv.play("如果你想知道什么是快樂星球的話,那我就帶你研究研究");
}
}
}
}
//消費者-->觀眾
class Watcher extends Thread {
TV tv;
public Watcher(TV tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
tv.watch();
}
}
}
//產品-->節目
class TV {
//演員表演,觀眾等待 T
//觀眾觀看,演員等待 F
String voice; // 表演的節目
boolean flag = true;
//表演
public synchronized void play(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;
}
}
第一篇文章,感謝家人們的閱讀
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/275780.html
標籤:java
