使用阻塞队列实现生产者与消费者

使用阻塞队列实现生产者与消费者


对于生产者与消费者是多线程中非常重要的一种实现,生产者生产的产品放入队列中,消费者消费队列中的产品,如果队列中没有了产品,消费者不再消费,如果队列中的产品满了,生产者就不再生产,对于生产者与消费者的实现,本文提供了两种方法:

  • 利用java提供的阻塞队列实现消费者与生产者
  • 自己写一个实现消费者与生产者的队列类

1.利用java提供的阻塞队列实现消费者与生产者


package com.hangzhou.victor.testsynchronized;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @description: 阻塞队列实现生产者与消费者
 * @author: victor
 * @date: 2018/12/24  17:25
 */
public class TestArrayBlockingQueue {

    public static void main(String[] args) {
        BlockingQueue<Character> bq = new LinkedBlockingQueue<>(5);

        new Thread(() -> {
            for (char i = 'A'; i <= 'G'; i++) {
                try {
                    System.out.println("生产者生产:" + i);
                    bq.put(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(() -> {
            for (int i = 0; i < 7; i++) {
                try {
                    Character poll = bq.take();
                    System.out.println("消费者消费:" + poll);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}
  • 这里生产者与消费者只提供了一个线程,也可以提供多个线程,这里都是一样的,不再赘述。

  • 对于阻塞队列,选择哪个都是一样的,只不过LinkedBlockingQueue有空参构造方法,ArrayBlockingQueue没有空参构造方法,创建时必须指定容量,但是,他们使用的方法都是put()take()

  • 对于阻塞队列一定要用其中的put()take()方法才能实现生产者与消费者线程的阻塞,具体其他方法的描述请参考java API。
    在这里插入图片描述

2. 自己写一个实现消费者与生产者的队列类


package com.hangzhou.victor.testsynchronized;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description:   生产者与消费者
 * @author: victor
 * @date: 2020/10/9  21:33
 */
public class TestProducerAndConsumer {
    public static void main(String[] args) {
        MyQueue mq = new MyQueue();
        Producer1 p1 = new Producer1(mq);
        Producer2 p2 = new Producer2(mq);
        Consumer c1 = new Consumer(mq);
        Consumer c2 = new Consumer(mq);

        p1.start();
        p2.start();
        c1.start();
        c2.start();

    }
}

class Consumer extends Thread {
    MyQueue mq;

    public Consumer(MyQueue mq) {
        this.mq = mq;
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(mq.poll()+"被"+Thread.currentThread().getName()+"移除");
        }
    }
}


class Producer1 extends Thread {
    MyQueue mq;

    public Producer1(MyQueue mq) {
        this.mq = mq;
    }

    @Override
    public void run() {
        for (char ch = 'A'; ch <= 'E'; ch++) {
            mq.offer(ch);
        }
    }
}

class Producer2 extends Thread {
    MyQueue mq;

    public Producer2(MyQueue mq) {
        this.mq = mq;
    }

    @Override
    public void run() {
        for (char ch = 'F'; ch <= 'J'; ch++) {
            mq.offer(ch);
        }
    }
}

class MyQueue {            //myqueue是临界资源
    private List vaules = new ArrayList();
    private int max = 4;

    public synchronized void offer(Object obj) {
        while (vaules.size() >= max) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.notifyAll();
        System.out.println(Thread.currentThread().getName() + "存入第" + (vaules.size() + 1) + "个值");
        vaules.add(obj);

    }

    public synchronized Object poll() {
        while (vaules.size() == 0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.notifyAll();           //唤醒因mq对象而进入无限期等待的线程对象所有
        return vaules.remove(0);
    }

    public void show() {
        for (Object vaule : vaules) {
            System.out.println(vaule);
        }
    }
}
  • 这里自己的实现感觉还是比较麻烦的,推荐第一种写法。

  • 当队列中的产品生产满了之后,生产者线程就进入阻塞状态,当队列中的产品消费完之后,消费者线程就进入阻塞状态,无论生产者和消费者都要唤醒所有的线程,以防止生产者只唤醒了生产者,消费者只唤醒了消费者导致无限阻塞状态。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值