当前位置: 代码迷 >> 综合 >> 使用多线程实现一个阻塞队列
  详细解决方案

使用多线程实现一个阻塞队列

热度:61   发布时间:2024-02-20 00:44:45.0
原理:使用jvm锁机制和一个普通队列共同实现一个阻塞队列package com.es.demo;
import lombok.extern.slf4j.Slf4j;
import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;/*** 使用多线程实现一个阻塞队列** @author renpl*/
@Slf4j
public class MyBlockQueue {// 初始化一个普通队列private final LinkedList<Object> list = new LinkedList<>();// 初始化一个计数器用于记录集合中添加的元素private final AtomicInteger counter = new AtomicInteger();// 初始化队列元素的最小数private int minSize = 0;// 初始化队列元素的最大数private int maxSize;// 初始化一个对象,用于加锁private Object lock = new Object();// 构造函数初始化一个制定大小的队列public MyBlockQueue(int maxSize) {this.maxSize = maxSize;}/*** 阻塞队列添加方法** @param obj* @throws InterruptedException*/private void put(Object obj) {try {synchronized (lock) {while (maxSize == counter.get()) {log.debug("队列已满");lock.wait();}// 队列中添加元素list.add(obj);// 计数器加1counter.incrementAndGet();// 唤醒其他正在排队向队列中添加元素的线程lock.notify();}} catch (InterruptedException e) {log.error("队列中添加元素发生异常", e);}}/*** 阻塞队列获取并移除元素** @return* @throws InterruptedException*/private Object take() {try {synchronized (lock) {while (minSize == counter.get()) {log.debug("此时队列中没有元素");lock.wait();}// 获取队列中的元素并且从队列中移除Object obj = list.removeFirst();// 计数器减1counter.decrementAndGet();// 唤醒其他正在排队从队列中获取元素的线程lock.notify();return obj;}} catch (InterruptedException e) {log.error("获取并移除队列中元素发生异常", e);}return null;}/*** 测试** @param args*/public static void main(String[] args) {// 主线程先把队列填满MyBlockQueue blockQueue = new MyBlockQueue(2);blockQueue.put("one");blockQueue.put("two");// 启动一个线程向填满的队列中新添加元素new Thread(new Runnable() {@Overridepublic void run() {log.info("新添加的元素:three");blockQueue.put("three");}}).start();// 获取并移除队列的元素,从而让上一个线程向队列中添加元素new Thread(new Runnable() {@Overridepublic void run() {String item = (String) blockQueue.take();log.info("获取到队列的元素:{}", item);}}).start();}
}
运行结果:

  09:56:56.848 [Thread-0] DEBUG com.es.demo.MyBlockQueue - 队列已满
  09:56:56.851 [Thread-0] INFO com.es.demo.MyBlockQueue - 新添加的元素:three
  09:56:56.851 [Thread-1] INFO com.es.demo.MyBlockQueue - 获取到队列的元素:one

  执行流程分析:主线程向blockQueue队列中添加了one,two两个元素,此时blockQueue队列已满;

线程Thread-0再次在09:56:56.848时刻向blockQueue中添加元素three,此时队列已阻塞了,控制台打印:

队列已满;这时候线程Thread-1在09:56:56.851时刻从队列中获取并移除one元素,同一时刻线程Thread-0

被唤醒向blockQueue中添加元素three,由于线程Thread-0执行的比线程Thread-1快,所以one元素被移除后

立马就添加元素three,打印:新添加的元素:three,最后又切换至线程Thread-1,执行打印:获取到队列的元素:one

  相关解决方案