版权声明:本文为博主原创文章,如需转载请标明出处。 https://blog.csdn.net/DGH2430284817/article/details/87189214
在线程池的线程全部开启后,之后的线程任务就会先放入阻塞队列,由阻塞队列把线程任务发放到线程池的空闲线程,当阻塞队列没有任务时,线程池就会一直阻塞,直到新的线程任务进入,具体的线程池细节可参考我的另一篇博客:https://blog.csdn.net/DGH2430284817/article/details/86697761
下面我们就使用synchronized锁来实现基础的阻塞队列
初始化阻塞队列参数:
public class BlockingQueue {
private int maxSize;//阻塞队列的最大容量
private List<String> list = new ArrayList<String>(); //元素集合
private final Object lock = new Object();//用final修饰锁,防止锁在使用的时候被修改引用导致锁失效
public BlockingQueue(int maxSize) {
this.maxSize = maxSize;
System.out.println("阻塞队列-" + Thread.currentThread().getName() + "已初始化长度为" + this.maxSize + "的队列");
}
.
. 其他方法代码
.
.
}
加入元素方法:
/**加入元素,如果阻塞队列满了则阻塞,直到有被元素取出
* @param element
* @throws InterruptedException
*/
public void put(String element) throws InterruptedException {
synchronized (lock) {
if (this.list.size() == this.maxSize) {
try {
System.out.println("阻塞队列:" + Thread.currentThread().getName() + "队列已满,阻塞并等待元素取出");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Thread.sleep(1000 * 1);//等待一秒
this.list.add(element);
System.out.println("阻塞队列:" + Thread.currentThread().getName() + "向队列中加入元素:" + element);
lock.notifyAll();
}
}
获取元素方法take():
/**获取元素,如果阻塞队列为空则阻塞,直到有新元素加入
* @return
*/
public String take() {
synchronized (lock) {
if (this.list.size() == 0) {
try {
System.out.println("阻塞队列:" + Thread.currentThread().getName() + "队列已空,阻塞并等待元素加入");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String result = this.list.remove(0);
System.out.println("阻塞队列:" + Thread.currentThread().getName() + "从队列中取出元素:" + result);
lock.notifyAll();
return result;
}
}
获取元素方法poll():
/**获取元素,如果阻塞队列为空则返回空
* @return
*/
public String poll() {
synchronized (lock) {
if (this.list.size() == 0) {
System.out.println("阻塞队列:" + Thread.currentThread().getName() + "队列已空,返回null");
return null;
}
String result = this.list.remove(0);
System.out.println("阻塞队列:" + Thread.currentThread().getName() + "从队列中取出元素:" + result);
lock.notifyAll();
return result;
}
}
测试:
public static void main(String[] args) {
BlockingQueue queue = new BlockingQueue(5);
new Thread(() -> {
try {
queue.put("1");
queue.put("2");
queue.put("3");
queue.put("4");
queue.put("5");
queue.put("6");
queue.put("7");
queue.put("8");
queue.put("9");
queue.put("10");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "A").start();
new Thread(() -> {
queue.take();
queue.take();
queue.take();
queue.take();
queue.take();
}, "C").start();
new Thread(() -> {
queue.poll();
queue.poll();
queue.poll();
queue.poll();
queue.poll();
}, "B").start();
}
结果:
阻塞队列-main已初始化长度为5的队列
阻塞队列:A向队列中加入元素:1
阻塞队列:A向队列中加入元素:2
阻塞队列:B从队列中取出元素:1
阻塞队列:B从队列中取出元素:2
阻塞队列:B队列已空,返回null
阻塞队列:B队列已空,返回null
阻塞队列:B队列已空,返回null
阻塞队列:C队列已空,阻塞并等待元素加入
阻塞队列:A向队列中加入元素:3
阻塞队列:A向队列中加入元素:4
阻塞队列:C从队列中取出元素:3
阻塞队列:C从队列中取出元素:4
阻塞队列:C队列已空,阻塞并等待元素加入
阻塞队列:A向队列中加入元素:5
阻塞队列:A向队列中加入元素:6
阻塞队列:A向队列中加入元素:7
阻塞队列:A向队列中加入元素:8
阻塞队列:C从队列中取出元素:5
阻塞队列:C从队列中取出元素:6
阻塞队列:C从队列中取出元素:7
阻塞队列:A向队列中加入元素:9
阻塞队列:A向队列中加入元素:10