前提
本示例是生产者向堆栈中 List 对象中放入数据,使消费者从 List 堆栈中取出数据。List 最大容量是 1
一生产一消费——操作栈
MyStack代码
import java.util.ArrayList;
import java.util.List;
public class MyStack {
private List list = new ArrayList();
synchronized public void push(){
try {
if(list.size() == 1){
this.wait();
}
list.add("anyString = "+ Math.random());
this.notify();
System.out.println("push = "+ list.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized public String pop(){
String returnValue = "";
try {
if(list.size() == 0){
this.wait();
}
returnValue = list.get(0)+"";
list.remove(0);
this.notify();
System.out.println("pop = "+ list.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
return returnValue;
}
}
MainThread代码
public class mainThread {
public static void main(String[] args) {
MyStack myStack = new MyStack();
ThreadP pThread = new ThreadP(myStack);
ThreadC cThread = new ThreadC(myStack);
pThread.start();
cThread.start();
}
}
class ThreadP extends Thread {
private MyStack myStack;
public ThreadP(MyStack myStack) {
super();
this.myStack = myStack;
}
public void run(){
while(true){
myStack.push();
}
}
}
class ThreadC extends Thread {
private MyStack myStack;
public ThreadC(MyStack myStack) {
super();
this.myStack = myStack;
}
public void run(){
while(true){
myStack.pop();
}
}
}
输出结果
程序运行结果是 size() 不会大于1,通过生产者/消费者模式,两个操作交替进行
一生产与多消费——操作栈:解决 wait 条件改变与假死
启动多个消费者,只需要在 mainThread 中启动多个消费者线程,MyStack 不用更改。代码如下:
public class mainThread {
public static void main(String[] args) {
MyStack myStack = new MyStack();
ThreadP pThread = new ThreadP(myStack);
ThreadC cThread1 = new ThreadC(myStack);
ThreadC cThread2 = new ThreadC(myStack);
pThread.start();
cThread1.start();
cThread2.start();
}
}
class ThreadP extends Thread {
private MyStack myStack;
public ThreadP(MyStack myStack) {
super();
this.myStack = myStack;
}
public void run(){
while(true){
myStack.push();
}
}
}
class ThreadC extends Thread {
private MyStack myStack;
public ThreadC(MyStack myStack) {
super();
this.myStack = myStack;
}
public void run(){
while(true){
myStack.pop();
}
}
}
运行结果如下所示:
此问题的出现就是因为 MyStack 类中使用了 if 语句作为条件判断。
因为条件发生改变的时候并没有得到及时的响应,所以多个呈 wait 状态的线程被召唤,继而执行 list.remove(0) 代码出现异常。解决策略就是讲 if 更换为 while 语句。
解决办法当然还是采用 notifyAll()。将 MyStack 中两处 notify 变更为 notifyAll() 后即可。
多生产与一消费)——操作栈
启动多个生产者,只需要在 mainThread 中启动多个生产者线程,MyStack 不用更改。代码如下:
public class mainThread {
public static void main(String[] args) {
MyStack myStack = new MyStack();
ThreadP pThread1 = new ThreadP(myStack);
ThreadP pThread2 = new ThreadP(myStack);
ThreadC cThread = new ThreadC(myStack);
pThread1.start();
pThread2.start();
cThread.start();
}
}
class ThreadP extends Thread {
private MyStack myStack;
public ThreadP(MyStack myStack) {
super();
this.myStack = myStack;
}
public void run(){
while(true){
myStack.push();
}
}
}
class ThreadC extends Thread {
private MyStack myStack;
public ThreadC(MyStack myStack) {
super();
this.myStack = myStack;
}
public void run(){
while(true){
myStack.pop();
}
}
}
采用上面 “一生产/多消费”模式依旧可以唱功运行。
多生产者与多消费者:操作栈
启动多个生产者和多个消费者,只需要在 mainThread 中启动多个生产者线程和多个消费者线程,MyStack 不用更改。代码如下:
public class mainThread {
public static void main(String[] args) {
MyStack myStack = new MyStack();
ThreadP pThread1 = new ThreadP(myStack);
ThreadP pThread2 = new ThreadP(myStack);
ThreadC cThread = new ThreadC(myStack);
pThread1.start();
pThread2.start();
cThread.start();
}
}
class ThreadP extends Thread {
private MyStack myStack;
public ThreadP(MyStack myStack) {
super();
this.myStack = myStack;
}
public void run(){
while(true){
myStack.push();
}
}
}
class ThreadC extends Thread {
private MyStack myStack;
public ThreadC(MyStack myStack) {
super();
this.myStack = myStack;
}
public void run(){
while(true){
myStack.pop();
}
}
}