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日

相关文章

  • Spring boot2+jpa+thymeleaf实现增删改查

    以下是详细讲解“Spring boot2+jpa+thymeleaf实现增删改查”的完整攻略。 1. 准备工作 在开始实现增删改查功能之前,我们需要进行一些准备工作。 1.1 创建Spring Boot工程 首先,我们需要创建一个Spring Boot工程,在这里可以使用Spring Initializr快速创建一个基础工程。在创建工程的过程中需要添加依赖S…

    Java 2023年5月20日
    00
  • Java算法真题详解运用单调栈

    Java算法真题详解运用单调栈攻略 1. 什么是单调栈 单调栈是指栈中元素单调递增或递减的栈。 单调栈在算法中的应用比较广泛,经常用来解决类似于比当前数大的第一个数、比当前数小的第一个数等等问题。 2. 单调栈解法 单调栈的解法分为两类:单调递增栈和单调递减栈。具体的应用方式如下: 2.1. 单调递增栈 单调递增栈指栈中元素单调递增,栈底元素最小。 单调递增…

    Java 2023年5月19日
    00
  • Java Arrays.sort()用法详解

    Java Arrays.sort()用法详解 Arrays.sort()是Java中的一个标准库函数,用于对数组进行排序,它可以对任何类型的数组进行排序(例如,整型、浮点数、字符串等等),本文将对该函数的用法进行详解。 语法 Arrays.sort(array, [fromIndex], [toIndex], [comparator]) array 参数是要…

    Java 2023年5月26日
    00
  • ajax+jsp草稿自动保存的实现代码

    下面我给您提供一个使用Ajax+JSP实现草稿自动保存的攻略。 1. 实现步骤 1.1 页面结构 首先,我们需要建立一个编辑器页面,也就是用户可以输入内容的页面。在这个页面中,我们可以使用一些现成的编辑器,如UEditor、Quill等。 1.2 Ajax请求 在用户编辑文本时,我们可以使用Ajax发送请求,将用户输入的内容提交到后端进行处理。由于草稿自动保…

    Java 2023年6月15日
    00
  • SpringBoot项目鉴权的4种方式小结

    下面我们来详细讲解SpringBoot项目鉴权的4种方式,包括:JWT鉴权、Session鉴权、OAuth2鉴权以及SaaS鉴权。 1. JWT鉴权 JWT鉴权是目前最常用的鉴权方式之一,其具有轻量级、无状态、较高的安全性等特点。这里简单介绍一下JWT鉴权的原理: 在用户登录成功之后,服务器会将用户信息通过一定的加密方式生成一份Token,并将其返回给客户端…

    Java 2023年6月3日
    00
  • java8 Math新增方法介绍

    Java8 Math新增方法介绍 Java8中Math类新增了一些数学方法,让我们能够更加便捷地进行数学计算。这篇文章将介绍Java8 Math新增的一些常用方法,以及相应的示例说明。 Math.addExact(int x, int y) 这个方法是将两个int类型的数相加,并返回它们的和。如果溢出,即产生一个结果超出了int类型的最大值或最小值范围,将会…

    Java 2023年5月26日
    00
  • Java的Hibernate框架中的基本映射用法讲解

    Java的Hibernate框架是一种非常流行的ORM(对象关系映射)框架,它提供了许多映射用法的实现,通过这些映射用法可以将数据库中的数据与Java对象进行自动转换。下面详细讲解一下Hibernate框架中的基本映射用法。 Hibernate框架中的基本映射用法 1. 建立数据表与Java类的映射 Hibernate框架中的一个最基本的映射用法就是建立数据…

    Java 2023年5月19日
    00
  • 详解Spring全局异常处理的三种方式

    我会详细讲解“详解Spring全局异常处理的三种方式”的完整攻略,并给出两个示例说明。 1. 为什么需要全局异常处理 Spring应用程序在运行过程中难免会遇到一些异常,如异常的输入、网络连接中断等。这些异常无法避免,但我们需要对这些异常进行合理的处理以便程序更健壮。而全局异常处理正是为此而设。 全局异常处理是指在应用程序中捕获所有未被捕获的异常,并尝试对它…

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