阻塞队列是什么
在将阻塞队列前,我们想先来回忆一下什么是普通队列?
普通队列:容器,允许放入元素,取出元素,分为FIFO(先进先出)(有容量上限/无容量上限)、优先级队列。
在普通队列中,队列满了则不能继续放入元素,可以继续执行其他的动作。
队列是空的的时候,不能取出元素,可以执行其他动作。
阻塞队列:放入失败/获取失败之后,直接放弃 CPU(阻塞)。直到条件满足(队列内有空间了或者队列中有元素)被唤醒。
使用阻塞队列组成的模式被称为 生产者(Producer)消费者(Customer)模式。
阻塞队列的使用
利用阻塞队列计算斐波那契数列 代码
原理如下:
package blocking_queue_fib;
import java.util.concurrent.BlockingQueue;
public class CalcTask implements Runnable{
public CalcTask(BlockingQueue<Integer> taskBlockingQueue, BlockingQueue<NR> resultBlockingQueue) {
this.taskBlockingQueue=taskBlockingQueue;
this.resultBlockingQueue=resultBlockingQueue;
}
private static long fib(int n){
if(n<0){
return -1;
}
if(n<=1){
return 1;
}
return fib(n-1)+fib(n-2);
}
private final BlockingQueue<Integer> taskBlockingQueue;
private final BlockingQueue<NR> resultBlockingQueue;
@Override
public void run() {
try{
while(true){
int n= taskBlockingQueue.take();
long r=fib(n);
resultBlockingQueue.put(new NR(n,r));
}
}catch(InterruptedException ignored){
}
}
}
package blocking_queue_fib;
import java.util.Scanner;
import java.util.concurrent.BlockingQueue;
public class MainTask implements Runnable{
private final Scanner scanner;
private final BlockingQueue<Integer> taskBlockingQueue;
public MainTask(Scanner scanner, BlockingQueue<Integer> taskBlockingQueue) {
this.scanner = scanner;
this.taskBlockingQueue = taskBlockingQueue;
}
@Override
public void run() {
try{
while(true){
System.out.println("请输入要计算的n:");
int n=scanner.nextInt();
taskBlockingQueue.put(n);
}
}catch(InterruptedException ignored){
}
}
}
package blocking_queue_fib;
public class NR {
public final int n;
public final long r;
public NR(int n, long r) {
this.n = n;
this.r = r;
}
}
package blocking_queue_fib;
import java.util.concurrent.BlockingQueue;
public class PrintTask implements Runnable{
private final BlockingQueue<NR> resultBlockingQueue;
public PrintTask(BlockingQueue<NR> resultBlockingQueue) {
this.resultBlockingQueue = resultBlockingQueue;
}
@Override
public void run() {
try{
while(true){
NR nr=resultBlockingQueue.take();
System.out.printf("fib(%d) 的结果是 %d\n", nr.n, nr.r);
}
}catch(InterruptedException ignored){}
}
}
package blocking_queue_fib;
import java.util.Scanner;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class Main {
public static void main(String[] args) {
// 定义两个阻塞队列
BlockingQueue<Integer> taskBlockingQueue = new LinkedBlockingQueue<>();
BlockingQueue<NR> resultBlockingQueue = new LinkedBlockingQueue<>();
// 创建打印线程
PrintTask printTask = new PrintTask(resultBlockingQueue);
Thread printThread = new Thread(printTask, "打印线程");
printThread.start();
// 创建计算线程
CalcTask calcTask = new CalcTask(taskBlockingQueue, resultBlockingQueue);
for (int i = 0; i < 4; i++) {
Thread calcThread = new Thread(calcTask, "计算线程-" + i);
calcThread.start();
}
// 主线程做自己的主任务
Scanner scanner = new Scanner(System.in);
MainTask mainTask = new MainTask(scanner, taskBlockingQueue);
mainTask.run(); // 在主线程中自己执行这个任务
}
}