Java并发之BlockingQueue的使用

Java并发之BlockingQueue的使用

在Java的并发编程中,常常需要使用阻塞队列来进行线程间的通信。BlockingQueue提供了一种线程安全、并发的队列实现方式,其中阻塞的特性保证了在队列为空或满时线程的阻塞和唤醒。

BlockingQueue简介

BlockingQueue是Java.util.concurrent包下面的一个接口,它定义了阻塞队列的一些基本操作,包括take、put、offer、poll等方法,是实现生产者-消费者模型的重要工具。

BlockingQueue通常结合着线程池或者定时器一起使用。

BlockingQueue常见的实现类有:
- PriorityBlockingQueue:基于优先级的无限阻塞队列
- ArrayBlockingQueue:基于数组的有界阻塞队列
- LinkedBlockingQueue:基于链表的无界阻塞队列
- SynchronousQueue:不存储元素的阻塞队列

BlockingQueue的使用

基本方法

以下是BlockingQueue的四种基本方法的说明:

  • put(E e):将元素插入到队尾,如果队列满,则阻塞等待空间可用
  • take():返回并移除队头元素,如果队列为空,阻塞等待可用元素
  • offer(E e):将元素插入到队尾,如果队列已满则返回false
  • poll(long timeout, TimeUnit unit):等待指定时长来获取队列头部的元素,如果在等待时间内没有可用元素,则返回null

示例一:生产者-消费者模型

生产者线程将数据放入阻塞队列中,消费者线程从阻塞队列中取出数据进行处理。为了刻画生产者和消费者,这里使用两个不同的线程来演示。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class ProducerConsumerDemo {

    private static final int CAPACITY = 5;
    private static BlockingQueue<String> queue = new ArrayBlockingQueue<>(CAPACITY);

    public static void main(String[] args) {
        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);
        new Thread(producer).start();
        new Thread(consumer).start();
    }

    static class Producer implements Runnable {

        private BlockingQueue<String> queue;

        Producer(BlockingQueue<String> queue) {
            this.queue = queue;
        }

        @Override
        public void run() {
            try {
                queue.put("1");
                System.out.println("Produced 1");
                Thread.sleep(1000);
                queue.put("2");
                System.out.println("Produced 2");
                Thread.sleep(1000);
                queue.put("3");
                System.out.println("Produced 3");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class Consumer implements Runnable {

        private BlockingQueue<String> queue;

        Consumer(BlockingQueue<String> queue) {
            this.queue = queue;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(5000);
                System.out.println("Consumed " + queue.take());
                Thread.sleep(1000);
                System.out.println("Consumed " + queue.take());
                Thread.sleep(1000);
                System.out.println("Consumed " + queue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

上述代码中,Producer线程将三个数据依次放入到阻塞队列中,每放入一个数据就打印出来。Consumer线程则从队列中取出三个数据进行处理。

示例二:多任务并行处理

在一个线程池中,多个任务可以并发地进行处理,BlockingQueue可以很容易地实现这种需求。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TaskHandlerDemo {

    private static final int THREAD_POOL_SIZE = 3;
    private static final int TASK_QUEUE_SIZE = 10;
    private static BlockingQueue<String> taskQueue = new ArrayBlockingQueue<>(TASK_QUEUE_SIZE);

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
        for (int i = 0; i < THREAD_POOL_SIZE; i++) {
            executorService.submit(new Worker(i));
        }

        for (int i = 0; i < TASK_QUEUE_SIZE; i++) {
            try {
                taskQueue.put("Task " + i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        executorService.shutdown();
    }

    static class Worker implements Runnable {

        private int id;

        Worker(int id) {
            this.id = id;
        }

        @Override
        public void run() {
            String task;
            while (true) {
                try {
                    task = taskQueue.take();
                    System.out.println("Worker " + id + " handles " + task);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

上述代码中,创建了一个线程池和一个大小为10的BlockingQueue。在第一个循环中,提交了三个Worker任务。在第二个循环中,向队列中加入10个任务,而这些任务是互不相同的。这样子程序就会开始并行处理这些任务。

总结

  • BlockingQueue提供了一种线程安全、并发的队列实现方式
  • BlockingQueue是实现生产者-消费者模型的重要工具
  • BlockingQueue一般结合线程池或者定时器一起使用
  • 阻塞队列通常有以下几种实现:PriorityBlockingQueue、ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue。

希望这篇文章对大家有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发之BlockingQueue的使用 - Python技术站

(0)
上一篇 2023年5月16日
下一篇 2023年5月16日

相关文章

  • Java多线程Thread类的使用详解

    Java多线程Thread类的使用详解 简介 Java 程序是单线程的,但是程序中很多场景需要同时处理多个任务,因此 Java 提供了多线程并发处理机制,可以快速有效地解决这个问题。Thread 类是 Java 多线程的核心类之一,在 Java 中创建新线程有两种方法,一种是继承 Thread 类,另一种是实现 Runnable 接口,在本文中将详细讲解 T…

    多线程 2023年5月17日
    00
  • python多线程超详细详解

    Python多线程超详细攻略 本文将为大家详细讲解Python多线程的使用,以及代码示例说明,帮助读者更加深入理解Python多线程的核心概念。 什么是Python多线程 Python多线程是通过在应用程序中运行多个线程来实现同时执行多个任务。Python多线程可以帮助提高应用程序的性能,尤其适用于IO密集型任务。 Python多线程模块 Python的多线…

    多线程 2023年5月17日
    00
  • java多线程下载实例详解

    Java多线程下载实例详解 本文将介绍Java多线程下载的实现方法和步骤,并提供两个示例说明。 实现步骤 Java多线程下载的实现步骤如下: 获取需要下载的文件的URL地址。 创建多个线程,每个线程负责下载文件的不同部分。 启动多个线程,通过HTTP请求下载各自负责的文件部分。 合并下载完成的文件部分。 完成文件下载。 示例一:Java多线程文件下载 以下示…

    多线程 2023年5月17日
    00
  • PHP+Redis链表解决高并发下商品超卖问题(实现原理及步骤)

    下面是“PHP+Redis链表解决高并发下商品超卖问题(实现原理及步骤)”的完整攻略: 一、问题分析 在高并发情况下,如果不采用合适的并发控制方案,会导致商品超卖问题。假设一个购买的过程分为三步: 判断商品库存是否足够 如果库存足够,则扣减库存 生成订单并支付 如果多个用户同时执行第一步,判断商品库存的时候会发现库存充足,就都会执行第二步,扣减库存,这样就会…

    多线程 2023年5月16日
    00
  • 详解Java多线程和IO流的应用

    详解Java多线程和IO流的应用 简介 Java多线程和IO流是Java编程中非常重要的两个主题。多线程可以帮助我们充分利用计算机多核处理器的性能,从而提高程序运行效率。而IO流则可以帮助我们进行文件读写、网络通信等操作。本文将从基础概念讲解和实际例子两个方面介绍Java多线程和IO流的应用。 基础概念讲解 多线程 Java多线程是指在同一时刻,多条线程同时…

    多线程 2023年5月17日
    00
  • c#使用多线程的几种方式示例详解

    Markdown格式文本是一种轻量级的标记语言,可以方便地对文本进行排版和格式化,使得文本更具可读性和可维护性。在本文中,我们将详细介绍如何使用Markdown格式文本编写“C#使用多线程的几种方式示例详解”的完整攻略,包含至少两条示例说明。 C#使用多线程的几种方式示例详解 概述 多线程是一种并发执行模型,可以提高程序性能和响应速度。C#是一种支持多线程编…

    多线程 2023年5月17日
    00
  • Java多线程三种主要实现方式解析

    Java多线程三种主要实现方式解析 在Java中,多线程的实现方式有三种:继承Thread类、实现Runnable接口和实现Callable接口。本文将详细介绍这三种实现方式的使用方法及优缺点。 继承Thread类 第一种实现方式是继承Thread类,并重写其run()方法。这种方式的优点在于编写简单,易于理解。下面是示例代码: public class M…

    多线程 2023年5月17日
    00
  • 基于线程、并发的基本概念(详解)

    基于线程、并发的基本概念(详解) 什么是线程和并发? 线程 线程是程序执行的一条路径,每个线程都是独立的,具有自己的栈空间和程序计数器。同一个程序中如果有多个线程,它们可以并发执行,即同时执行,换句话说,多线程可以用来实现程序的并发性。 并发 并发,指的是系统能够同时处理多个任务的能力。例如,多个线程在同时执行不同的任务,或者同一个线程在同时执行多个任务,都…

    多线程 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部