多线程-阻塞队列

文章通过一个Java示例展示了如何利用阻塞队列(BlockingQueue)实现生产者消费者模式,计算斐波那契数列。CalcTask线程作为生产者放入计算任务,MainTask线程读取输入并放入任务队列,PrintTask线程作为消费者从结果队列中取出并打印结果。阻塞队列在队列满或空时会自动阻塞相应操作,等待条件满足后再继续执行。
摘要由CSDN通过智能技术生成

阻塞队列是什么

在将阻塞队列前,我们想先来回忆一下什么是普通队列?

普通队列:容器,允许放入元素,取出元素,分为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(); // 在主线程中自己执行这个任务
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值