在Java中,負(fù)責(zé)產(chǎn)生數(shù)據(jù)的模塊是生產(chǎn)者,負(fù)責(zé)使用數(shù)據(jù)的模塊是消費(fèi)者. 生產(chǎn)者消費(fèi)者解決數(shù)據(jù)的平衡問(wèn)題,即先有數(shù)據(jù)然后才能使用,沒(méi)有數(shù)據(jù)時(shí),消費(fèi)者需要等待。
package com.wkcto.producerdata;
/**
* 定義一個(gè)操作數(shù)據(jù)的類
* 北京動(dòng)力節(jié)點(diǎn)老崔
*/
public class ValueOP {
private String value = "";
//定義方法修改value字段的值
public void setValue(){
synchronized ( this ){
//如果value值不是""空串就等待
while ( !value.equalsIgnoreCase("")){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果value字段值是容串, 就設(shè)置value字段的值
String value = System.currentTimeMillis() + " - " + System.nanoTime();
System.out.println("set設(shè)置的值是: " + value);
this.value = value;
// this.notify(); //在多生產(chǎn)者多消費(fèi)者環(huán)境中,notify()不能保證是生產(chǎn)者喚醒消費(fèi)者,如果生產(chǎn)者喚醒的還是生產(chǎn)者可能會(huì)出現(xiàn)假死的情況
this.notifyAll();
}
}
//定義方法讀取字段值
public void getValue(){
synchronized (this){
//如果value是空串就等待
while ( value.equalsIgnoreCase("")){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//不是空串,讀取 字段值
System.out.println("get的值是: " + this.value);
this.value = "";
this.notifyAll();
}
}
}
package com.wkcto.producerdata;
/**
* 定義線程類模擬生產(chǎn)者
* 北京動(dòng)力節(jié)點(diǎn)老崔
*/
public class ProducerThread extends Thread {
//生產(chǎn)者生產(chǎn)數(shù)據(jù)就是調(diào)用ValueOP類的setValue方法給value字段賦值
private ValueOP obj;
public ProducerThread(ValueOP obj) {
this.obj = obj;
}
@Override
public void run() {
while (true){
obj.setValue();
}
}
}
package com.wkcto.producerdata;
/**
* 定義線程類模擬消費(fèi)者
* 北京動(dòng)力節(jié)點(diǎn)老崔
*/
public class ConsumerThread extends Thread {
//消費(fèi)者使用數(shù)據(jù), 就是使用ValueOP類的value字段值
private ValueOP obj;
public ConsumerThread(ValueOP obj) {
this.obj = obj;
}
@Override
public void run() {
while (true){
obj.getValue();
}
}
}
package com.wkcto.producerdata;
/**
* 測(cè)試多生產(chǎn),多消費(fèi)的情況
* 北京動(dòng)力節(jié)點(diǎn)老崔
*/
public class Test2 {
public static void main(String[] args) {
ValueOP valueOP = new ValueOP();
ProducerThread p1 = new ProducerThread(valueOP);
ProducerThread p2 = new ProducerThread(valueOP);
ProducerThread p3 = new ProducerThread(valueOP);
ConsumerThread c1 = new ConsumerThread(valueOP);
ConsumerThread c2 = new ConsumerThread(valueOP);
ConsumerThread c3 = new ConsumerThread(valueOP);
p1.start();
p2.start();
p3.start();
c1.start();
c2.start();
c3.start();
}
}
使生產(chǎn)者把數(shù)據(jù)存儲(chǔ)到List集合中, 消費(fèi)者從List集合中取數(shù)據(jù),使用List集合模擬棧。
package com.wkcto.produerstack;
import java.util.ArrayList;
import java.util.List;
/**
* 模擬棧
* 北京動(dòng)力節(jié)點(diǎn)老崔
*/
public class MyStack {
private List list = new ArrayList(); //定義集合模擬棧
private static final int MAX = 3; //集合的最大容量
//定義方法模擬入棧
public synchronized void push(){
//當(dāng)棧中的數(shù)據(jù)已滿 就等待
while ( list.size() >= MAX ){
System.out.println(Thread.currentThread().getName() + " begin wait....");
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String data = "data--" + Math.random();
System.out.println( Thread.currentThread().getName() + "添加了數(shù)據(jù): " + data);
list.add(data);
// this.notify(); //當(dāng)多個(gè)生產(chǎn)者多個(gè)消費(fèi)者時(shí),使用notify()可能會(huì)出現(xiàn)假死的情況
this.notifyAll();
}
//定義方法模擬出棧
public synchronized void pop(){
//如果沒(méi)有數(shù)據(jù)就等待
while ( list.size() == 0 ){
try {
System.out.println(Thread.currentThread().getName() + " begin wait....");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println( Thread.currentThread().getName() + "出棧數(shù)據(jù):" + list.remove(0) );
this.notifyAll();
}
}
package com.wkcto.produerstack;
/**
* 生產(chǎn)者線程
* 北京動(dòng)力節(jié)點(diǎn)老崔
*/
public class ProduerThread extends Thread {
private MyStack stack;
public ProduerThread(MyStack stack) {
this.stack = stack;
}
@Override
public void run() {
while (true){
stack.push();
}
}
}
package com.wkcto.produerstack;
/**
* 消費(fèi)線程
* 北京動(dòng)力節(jié)點(diǎn)老崔
*/
public class ConsumerThread extends Thread {
private MyStack stack;
public ConsumerThread(MyStack stack) {
this.stack = stack;
}
@Override
public void run() {
while (true){
stack.pop();
}
}
}
package com.wkcto.produerstack;
/**
* 測(cè)試多生產(chǎn)多消費(fèi)的情況
* 北京動(dòng)力節(jié)點(diǎn)老崔
*/
public class Test02 {
public static void main(String[] args) {
MyStack stack = new MyStack();
ProduerThread p = new ProduerThread(stack);
ProduerThread p2 = new ProduerThread(stack);
ProduerThread p3 = new ProduerThread(stack);
ConsumerThread c1 = new ConsumerThread(stack);
ConsumerThread c2 = new ConsumerThread(stack);
ConsumerThread c3 = new ConsumerThread(stack);
p.setName("生產(chǎn)者1號(hào)");
p2.setName("生產(chǎn)者2號(hào)");
p3.setName("生產(chǎn)者3號(hào)");
c1.setName("消費(fèi)者1號(hào)");
c2.setName("消費(fèi)者2號(hào)");
c3.setName("消費(fèi)者3號(hào)");
p.start();
p2.start();
p3.start();
c1.start();
c2.start();
c3.start();
}
}