《七》实际应用——生产者与消费者模型

Java并发编程系列文章
《一》多线程基础——Java线程与进程的基本概念
《二》多线程基础——Java线程入门类和接口
《三》多线程基础——Java线程组和线程优先级
《四》多线程基础——Java线程生命周期及转换
《五》多线程基础——Java线程间的通信(互斥与协作)
《六》实际应用——如何优雅的关闭线程
《七》实际应用——生产者与消费者模型

  并发编程(多线程)一直以来都是程序员头疼的难题。曾经听别人总结过并发编程的第一原则,那就是不要写并发程序,哈哈哈。后来发现,这样能够显著提高程序响应和吞吐量的利器,哪还能忍得住不会用呢?
  整理出《Java并发编程系列文章》,共计7篇,与君共勉。



1、会阻塞的生产者消费者模型,思考为什么?

生产者和消费者模型,应用非常广泛。这是一个经典错误的例子,引以为戒。

public class No6_produce_consumer_test{

    private int i = 0;
    final private static Object lock = new Object();
    private volatile boolean flag = false;

    public void produce(){
        synchronized (lock){
            if(flag){
                try {
                    System.out.println(Thread.currentThread().getName()+"-->waiting");
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else{
                i++;
                System.out.println(Thread.currentThread().getName()+"-->" + i);
                flag = true;
                lock.notify(); //todo 通知来消费
            }
        }
    }
    public void consumer(){
        synchronized (lock){
            if(flag){
                System.out.println(Thread.currentThread().getName()+"-->" + i);
                flag = false;
                lock.notify();  //todo 通知去生产
            }else{
                try {
                    System.out.println(Thread.currentThread().getName()+"-->waiting");
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        No6_produce_consumer_test pc = new No6_produce_consumer_test();
        Stream.of("P1","P2").forEach(n -> {
            new Thread(n){
                @Override
                public void run() {
                    while (true){
                        pc.produce();
                    }
                }
            }.start();
        });

        Stream.of("C1","C2").forEach(n -> {
            new Thread(n){
                @Override
                public void run() {
                    while (true){
                        pc.consumer();
                    }
                }
            }.start();
        });
    }
}

  运行结果就是两个生产者和两个消费者都会阻塞,程序卡死。原因就是:lock.notify()会随机唤醒一个放弃lock锁的阻塞的线程,可能唤醒生产者,也可能唤醒消费者。当生产者唤醒生产者,或者消费者唤醒消费者时,就会出现这样的问题。

2、正确的生产者消费者模型

public class No6_produce_consumer_dev {

    private int i = 0;
    final private static Object lock = new Object();
    private volatile boolean flag = false;

    public void produce(){
        synchronized (lock){
            while (flag){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            i++;
            System.out.println(Thread.currentThread().getName()+"-->" + i);
            flag = true;
            lock.notifyAll(); //todo 通知来消费
        }
    }
    public void consumer(){
        synchronized (lock){
            while(flag){
                System.out.println(Thread.currentThread().getName()+"-->" + i);
                flag = false;
                lock.notifyAll();  //todo 通知去生产
            }
            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        No6_produce_consumer_dev pc = new No6_produce_consumer_dev();
        Stream.of("P1","P2","P3","P4").forEach(n -> {
            new Thread(n){
                @Override
                public void run() {
                    while (true){
                        pc.produce();
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
        });

        Stream.of("C1","C2","C3","C4").forEach(n -> {
            new Thread(n){
                @Override
                public void run() {
                    while (true){
                        pc.consumer();
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
        });
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值