并发编程-synchronzied版本-多生产者-多消费者-模型

并发编程的口诀

  1. 线程 操作 资源类
  2. 判断 干活 通知
  3. 注意虚假唤醒

synchronized版本的 多生产 多消费注意的问题

  1. if判断标记,只会判断一次,会导致不该运行的线程运行了,导致数据错误,while判断标记,解决的线程获取到执行权限之后是否要执行的问题。
  2. notify只会唤醒一个线程,如果是唤醒本方线程就会没有意义,while判断标记 + notify 会导致死锁,notifyAll解决了本方线程一定会唤醒对方线程问题;

wait()和sleep()区别?

  1. 使用方式
    wait()可以设置时间,也可以不设置时间,sleep()必须设置时间
  2. 对锁和执行权的处理
    wait: 释放执行权限,释放锁
    sleep:释放执行全县,不释放锁

测试代码

@Test
    public void testSynchronize() throws InterruptedException {
        Resource resource = new Resource();

        Producer produceTask = new Producer(resource);
        new Thread(produceTask,"producer A.... ").start();
        new Thread(produceTask,"producer B.... ").start();

        Consumer consumer = new Consumer(resource);
        new Thread(consumer,"consumer C.... ").start();
        new Thread(consumer,"consumer D.... ").start();

        Thread.sleep(10000);
    }

共享的资源类

static class Resource {
        private String name;
        private int count = 1;
        private boolean flag = false;

        private final Object lock = new Object();

        public void set(String  name) {
            synchronized (this.lock) {
                while(flag) { //这个地方必须用while,否则,wait线程被唤醒的时候,不会再次判断flag,导致还没有消费,又生产新的;
                    try { this.lock.wait(); } catch (InterruptedException ignored) { }
                }
                this.name = name + count;
                count++;
                System.out.println(Thread.currentThread().getName() + " ...." + " 生产者 " + this.name);
                flag = true; // 设置flag和唤醒操作不能交换,可以思考了一下,如果交换会发生什么情况
                this.lock.notifyAll(); //这个地方一定要用notifyAll,否则可能会发生 没有唤醒消费者的线程(虚假唤醒)
            }
        }


        public void out() {
            synchronized (this.lock) {
                while(!flag) { // 同上
                    try { this.lock.wait(); } catch (InterruptedException ignored) {}
                }
                System.out.println(Thread.currentThread().getName() + " ...." + " 消费者 " + this.name);
                flag = false;
                this.lock.notifyAll();
            }
        }
    }

生产者

static class Producer implements Runnable{
        private final Resource resource;

        public Producer(Resource resource) {
            this.resource = resource;
        }
        @Override
        public void run() {
            for(int i = 0;i < 100;i++){
                resource.set("馒头");
            }
        }
    }

消费者

static class Consumer implements Runnable{
        private final Resource resource;

        public Consumer(Resource resource) {
            this.resource = resource;
        }
        @Override
        public void run() {
            for(int i = 0;i < 100;i++){
                resource.out();
            }
        }
    }

欢迎评论区交流 共同进步

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值