深入生产者与消费者模式

前提
本示例是生产者向堆栈中 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();
        }
    }
}

输出结果
image_1at13hj9u991ol91oas10igome9.png-5kB

程序运行结果是 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();
        }
    }
}

运行结果如下所示:
image_1at13r9nj1qnf1m3m1je3fe518a2m.png-57.4kB

此问题的出现就是因为 MyStack 类中使用了 if 语句作为条件判断。
image_1at142keu3dg8ll1cfokgs87u13.png-2.8kB
image_1at142td3j9g1b0l1h2113ti1pn71g.png-3.4kB
因为条件发生改变的时候并没有得到及时的响应,所以多个呈 wait 状态的线程被召唤,继而执行 list.remove(0) 代码出现异常。解决策略就是讲 if 更换为 while 语句。

image_1at149a8sp121bm11u3pk3v157d1t.png-61.9kB

解决办法当然还是采用 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();
        }
    }
}

image_1at14o1tob66pfl1mcm1p7d1bh02a.png-51.8kB

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值