在Java中,負責產生數據的模塊是生產者,負責使用數據的模塊是消費者. 生產者消費者解決數據的平衡問題,即先有數據然后才能使用,沒有數據時,消費者需要等待。
package com.wkcto.producerdata;
/**
* 定義一個操作數據的類
* 北京動力節點老崔
*/
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字段值是容串, 就設置value字段的值
String value = System.currentTimeMillis() + " - " + System.nanoTime();
System.out.println("set設置的值是: " + value);
this.value = value;
// this.notify(); //在多生產者多消費者環境中,notify()不能保證是生產者喚醒消費者,如果生產者喚醒的還是生產者可能會出現假死的情況
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;
/**
* 定義線程類模擬生產者
* 北京動力節點老崔
*/
public class ProducerThread extends Thread {
//生產者生產數據就是調用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;
/**
* 定義線程類模擬消費者
* 北京動力節點老崔
*/
public class ConsumerThread extends Thread {
//消費者使用數據, 就是使用ValueOP類的value字段值
private ValueOP obj;
public ConsumerThread(ValueOP obj) {
this.obj = obj;
}
@Override
public void run() {
while (true){
obj.getValue();
}
}
}
package com.wkcto.producerdata;
/**
* 測試多生產,多消費的情況
* 北京動力節點老崔
*/
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();
}
}
使生產者把數據存儲到List集合中, 消費者從List集合中取數據,使用List集合模擬棧。
package com.wkcto.produerstack;
import java.util.ArrayList;
import java.util.List;
/**
* 模擬棧
* 北京動力節點老崔
*/
public class MyStack {
private List list = new ArrayList(); //定義集合模擬棧
private static final int MAX = 3; //集合的最大容量
//定義方法模擬入棧
public synchronized void push(){
//當棧中的數據已滿 就等待
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() + "添加了數據: " + data);
list.add(data);
// this.notify(); //當多個生產者多個消費者時,使用notify()可能會出現假死的情況
this.notifyAll();
}
//定義方法模擬出棧
public synchronized void pop(){
//如果沒有數據就等待
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() + "出棧數據:" + list.remove(0) );
this.notifyAll();
}
}
package com.wkcto.produerstack;
/**
* 生產者線程
* 北京動力節點老崔
*/
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;
/**
* 消費線程
* 北京動力節點老崔
*/
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;
/**
* 測試多生產多消費的情況
* 北京動力節點老崔
*/
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("生產者1號");
p2.setName("生產者2號");
p3.setName("生產者3號");
c1.setName("消費者1號");
c2.setName("消費者2號");
c3.setName("消費者3號");
p.start();
p2.start();
p3.start();
c1.start();
c2.start();
c3.start();
}
}