Java多线程案例之阻塞队列详解

Java多线程案例之阻塞队列详解

什么是阻塞队列?

阻塞队列(Blocking Queue)是一个支持在队列的两端进行插入与删除的队列。常用的阻塞队列有ArrayBlockingQueue、LinkedBlockingQueue等。阻塞队列在多线程的场景下常被使用,因为当队列为空或达到容量上限时,线程往往会被阻塞。在队列空的情况下,从队列中获取元素的操作将会被阻塞,直到有元素加入到队列中;在队列满的情况下,插入元素的操作将会被阻塞,直到队列中有元素被移除。

Java中的阻塞队列

ArrayBlockingQueue

ArrayBlockingQueue 是一个基于数组结构实现的有界阻塞队列,其内部实现使用了ReentrantLock(可重入锁)来保证操作的线程安全性。

可以使用以下代码创建一个ArrayBlockingQueue:

BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);

LinkedBlockingQueue

LinkedBlockingQueue 是一个基于链表结构实现的有界(大小默认是Integer.MAX_VALUE)阻塞队列,其内部实现使用了两个ReentrantLock和两个Condition来保证对队列的插入和删除操作的线程安全性。

可以使用以下代码创建一个LinkedBlockingQueue:

BlockingQueue<String> queue = new LinkedBlockingQueue<>();

示例说明

ArrayBlockingQueue 示例

以下示例展示了一个使用ArrayBlockingQueue实现的生产者消费者模型。

public class ProducerConsumerDemo {

    private static BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);

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

    static class Producer implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    queue.put(new Random().nextInt(100));
                    System.out.println("生产者生产了一个商品,当前队列大小:" + queue.size());
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    static class Consumer implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    queue.take();
                    System.out.println("消费者消费了一个商品,当前队列大小:" +queue.size());
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这个示例中,生产者线程负责往阻塞队列中添加数据(即商品),如果队列已满,则会被阻塞。消费者线程负责从阻塞队列中取出数据(即消费商品),如果队列为空,则会被阻塞。

LinkedBlockingQueue 示例

以下示例展示了一个使用LinkedBlockingQueue实现的线程池模型。

public class ThreadPoolDemo {

    private static ExecutorService executorService = new ThreadPoolExecutor(3, 6, 500, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(10));

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            executorService.execute(new Worker(i));
        }

        executorService.shutdown();
    }

    static class Worker implements Runnable {

        private int id;

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

        @Override
        public void run() {
            try {
                System.out.println("当前执行线程:" + id + ",剩余线程:" + ((ThreadPoolExecutor) executorService).getQueue().remainingCapacity()));
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这个示例中,通过ThreadPoolExecutor来创建一个线程池,并使用LinkedBlockingQueue来作为任务队列。当线程池的线程数达到核心线程数(3)时,多余的任务会被放入LinkedBlockingQueue中等待执行。如果队列已满,则会阻塞新的任务。在这个示例中,最多执行9个Worker对象的run方法。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程案例之阻塞队列详解 - Python技术站

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

相关文章

  • 深入理解Java注解类型(@Annotation)

    深入理解Java注解类型(@Annotation) 引言 Java注解(Annotation)是Java语言中非常常见的一种特殊的语法元素,它可以为Java程序的编写提供更加丰富、灵活的方式。在本篇文章中,我们将详细地了解Java注解的定义、分类、使用方法及其在实际开发中的应用。 定义 Java注解(Annotation)是Java语言中的一种特殊语法元素,…

    Java 2023年5月20日
    00
  • Springboot初始化项目并完成登入注册的全过程

    Spring Boot初始化项目并完成登入注册的全过程 Spring Boot是一个非常流行的Java Web框架,它提供了许多方便的功能,如自动配置、快速开发和易于部署。本文将介绍如何使用Spring Boot初始化项目并完成登入注册的全过程,并提供两个示例。 步骤 以下是使用Spring Boot初始化项目并完成登入注册的全过程的步骤: 创建Spring…

    Java 2023年5月15日
    00
  • Android编程开发之打开文件的Intent及使用方法

    Android编程开发之打开文件的Intent及使用方法 在Android应用程序中,我们经常需要打开文件,比如图片、视频、音乐、文档等等,这时就要用到Intent。Intent是Android中的重要组成部分,它用于在不同应用程序之间进行交互,比如启动Activity、启动Service、启动BroadcastReceiver等等。 打开文件的Intent…

    Java 2023年6月15日
    00
  • SpringBoot开发存储服务器实现过程详解

    SpringBoot开发存储服务器实现过程详解 在 SpringBoot 中开发存储服务器可以方便地实现从文件上传到文件展示的全浏览器支持的存储方案。下面是如何使用 SpringBoot 来实现存储服务器的完整攻略: 第一步:创建 SpringBoot 项目 首先,在 IntelliJ IDEA 中创建一个空的 SpringBoot 项目。 第二步:添加文件…

    Java 2023年5月19日
    00
  • java多线程数据分页处理实例讲解

    Java多线程数据分页处理实例讲解 背景 在实际应用中,我们经常需要处理大量的数据,通常采用分页的方式进行处理,即每次只处理一页的数据,这样可以避免一次性加载大量数据造成内存溢出的问题。但是,当数据量较大时,单线程处理可能会比较缓慢,这时我们可以运用多线程进行加速处理。 分页算法 一般来说,分页算法的实现思路如下: 1. 根据总记录数和每页记录数计算总页数。…

    Java 2023年5月19日
    00
  • Spring整合ehCache全过程

    下面我将为您详细讲解Spring整合ehCache全过程的完整攻略,包含以下步骤: 引入依赖: 需要将spring-context-support和ehcache的依赖引入到项目中,pom.xml中的配置如下: <dependencies> <dependency> <groupId>org.springframework…

    Java 2023年5月20日
    00
  • java中进制的转换,Byte与16进制的转换方法

    Java中可以通过一些方法来进行进制转换,其中包括Byte与16进制的转换方法。下面我们详细来讲解Java中进制的转换以及Byte与16进制的转换方法。 进制的转换 在Java中,我们可以通过四种进制(二进制,八进制,十进制,十六进制)之间进行相互转换。以下是简单介绍每种进制的标识符: 二进制:以0b或0B开头,例如0b1010表示10。 八进制:以0开头,…

    Java 2023年5月26日
    00
  • java.lang.NullPointerException出现的几种原因及解决方案

    Java.lang.NullPointerException出现的几种原因及解决方案 简介 Java.lang.NullPointerException是Java程序中常见的运行时异常,一般会出现在调用空对象的方法或属性时。出现该异常的原因较为多样,本文将介绍其中几种常见的原因,并提出对应的解决方案,以帮助程序开发者快速解决问题。 原因和解决方案 1. 调用…

    Java 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部