生产者、消费者阻塞队列-高并发版

生产者、消费者模型-高并发

上一篇生产者、消费者模型-传统版中写了传统版(即生产一个消费一个)的生产者和消费者模型,本文记录一下生产者和消费者的高并发版本,即生产者和消费者无需互相等待,可以一直生产、一直消费

实现

主要是通过BlockingQueuevolatileAtomicInteger等方式来实现,保证线程安全和数据一致性

代码

  • 资源类
/**
 * 高并发的生产者消费者阻塞队列
 * 
 * volatile/cas/atomicInteger/blockingQueue/线程交互/原子引用
 *
 */
public class MyResource {

    /**
     * 保证多线程可见性 volatile
     */
    private volatile boolean FLAG = true; // 默认开启,消费和生产

	// 用于生产数据,使用原子类的CAS保证线程安全、数据一致性
    private AtomicInteger atomicInteger = new AtomicInteger();

    /**
     * 使用阻塞队列的阻塞特性实现生产者和消费者同时执行
     */
    private BlockingQueue<String> blockingQueue;

    public MyResource(BlockingQueue<String> blockingQueue) {
        this.blockingQueue = blockingQueue;
    }


    /**
     * 生产者生产数据,将数据放入到阻塞队列并设置超时时间,防止并发超时
     * @throws InterruptedException
     */
    public void prod() throws InterruptedException {
        String data;
        boolean returnVal;
        while (FLAG) {
            data = atomicInteger.incrementAndGet() + "";
            returnVal = blockingQueue.offer(data, 2, TimeUnit.SECONDS);
            if (returnVal) {
                System.out.println(Thread.currentThread().getName() + "\t插入队列" + data + "成功");
            } else {
                System.out.println(Thread.currentThread().getName() + "\t插入队列" + data + "失败");
            }
            // 这里使用sleep来设置生产者每秒生产一个,只是为了在控制台方便查看,可以注释
            TimeUnit.SECONDS.sleep(1);
        }
        System.out.println(Thread.currentThread().getName() + "\t停止");
    }


    /**
     * 消费者 消费数据,利用阻塞队列的特性获取数据,没有数据的时候阻塞获取
     *
     * @throws InterruptedException
     */
    public void consumer() throws InterruptedException {
        String data;
        while (FLAG) {
            data = blockingQueue.poll(2, TimeUnit.SECONDS);
            if (data == null || "".equals(data)) {
                // 消费者没有获取到数据,则停止
                FLAG = false;
                System.out.println(Thread.currentThread().getName() + "\t 超过2s没有获取到数据,消费者停止");
                return;
            }
            System.out.println(Thread.currentThread().getName() + "\t 消费数据" + data + "成功");
        }
    }

    /**
	 *  停止生产和消费
	 */
    public void stop() {
        FLAG = false;
    }

}
  • 测试调用
public class PC_ProdConsumer {

    public static void main(String[] args) throws InterruptedException {
        // 指定阻塞队列的实现类,以及指定阻塞队列的队列长度为10
        MyResource myResource = new MyResource(new ArrayBlockingQueue<>(10));

		// 开始生产
        new Thread(() -> {
            try {
                myResource.prod();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "AA").start();

		// 开始消费
        new Thread(() -> {
            try {
                myResource.consumer();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "BB").start();

		// 5秒后主线程停止,停止生产和消费
        TimeUnit.SECONDS.sleep(5);
        System.out.println(Thread.currentThread().getName() + "\t 停止生产和消费");
        myResource.stop();
    }

}

你可能感兴趣的:(Java,java,生产者消费者队列,生产消费模型呢)