一文探究ArrayBlockQueue函数及应用场景

一文探究ArrayBlockingQueue函数及应用场景

介绍

ArrayBlockingQueue是Java中的一个阻塞队列实现类,它是一个支持在队列的两端插入和删除元素的线程安全队列。它的大小是有限的,当队列已满时,插入操作会阻塞线程,直到队列有空闲空间;当队列为空时,获取操作会阻塞线程,直到队列有可用元素。

使用方法

创建ArrayBlockingQueue

ArrayBlockingQueue<T> queue = new ArrayBlockingQueue<T>(capacity);
  • T表示队列中元素的类型。
  • capacity是队列的容量,即队列最多能存放多少个元素。

插入元素

queue.put(element);
  • element表示要插入的元素。
  • 如果队列已经满了,则会阻塞线程。

删除元素

queue.take();
  • 如果队列为空,则会阻塞线程,并等待有可用元素。
  • 返回队列中最开始的元素,并将其从队列中删除。

查看队列元素个数和容量

queue.size();      // 查看队列元素个数
queue.remainingCapacity();  // 查看队列剩余容量

应用场景

多线程协作

在多线程编程中,一个线程可能要等待另一个线程的操作完成才能进行下一步操作。此时,可以使用ArrayBlockingQueue来实现两个线程之间的协作。

例如,一个线程需要获取另一个线程计算的结果,可以使用一个容量为1的ArrayBlockingQueue来进行线程之间的通信。

ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1);

Thread t1 = new Thread(() -> {
    int result = calculate();  // 计算结果
    try {
        queue.put(result);     // 将结果放入队列中
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});

Thread t2 = new Thread(() -> {
    try {
        int result = queue.take();  // 从队列中取出结果
        processResult(result);      // 处理结果
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});

t1.start();
t2.start();

任务队列

在一些系统中,可能需要有一个任务队列,用来存放需要执行的任务。当有空闲的线程时,从任务队列中取出一个任务进行处理。

此时,可以使用一个容量为N的ArrayBlockingQueue来实现任务队列的功能。

public class TaskQueue {
    private final int queueSize = 10;
    private ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(queueSize);   

    public void enqueueTask(Runnable task) {
        try {
            queue.put(task);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void processTasks() {
        while (true) {
            try {
                Runnable task = queue.take();
                task.run();   // 执行任务
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

// 在主线程中使用
TaskQueue taskQueue = new TaskQueue();

Thread t1 = new Thread(() -> taskQueue.processTasks());

Thread t2 = new Thread(() -> taskQueue.enqueueTask(() -> {
    //  执行任务
}));

t1.start();
t2.start();

示例说明

示例一:使用ArrayBlockingQueue实现生产者消费者模式

public class ProducerConsumerDemo {
    private static class Producer implements Runnable {
        private ArrayBlockingQueue<Integer> queue;

        public Producer(ArrayBlockingQueue<Integer> queue) {
            this.queue = queue;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                try {
                    queue.put(i);
                    System.out.println("生产者插入元素:" + i);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static class Consumer implements Runnable {
        private ArrayBlockingQueue<Integer> queue;

        public Consumer(ArrayBlockingQueue<Integer> queue) {
            this.queue = queue;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                try {
                    int element = queue.take();
                    System.out.println("消费者取出元素:" + element);
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);

        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);

        new Thread(producer).start();
        new Thread(consumer).start();
    }
}

在示例中我们创建了两个线程,一个是生产者线程,用于向队列中插入元素;一个是消费者线程,用于从队列中删除元素。

示例二:使用ArrayBlockingQueue实现线程池

public class ThreadPoolDemo {
    private ArrayBlockingQueue<Runnable> queue;
    private List<WorkerThread> threads;
    private volatile boolean shutdown = false;

    private class WorkerThread extends Thread {
        public void run() {
            while (!shutdown) {
                try {
                    Runnable task = queue.take();
                    task.run();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public ThreadPoolDemo(int poolSize, int queueSize) {
        queue = new ArrayBlockingQueue<>(queueSize);
        threads = new ArrayList<>(poolSize);

        for (int i = 0; i < poolSize; i++) {
            WorkerThread workerThread = new WorkerThread();
            workerThread.start();
            threads.add(workerThread);
        }
    }

    public void execute(Runnable task) {
        try {
            queue.put(task);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void shutdown() {
        shutdown = true;
        for (WorkerThread thread : threads) {
            thread.interrupt();
        }
    }
}

// 在主线程中使用
ThreadPoolDemo threadPool = new ThreadPoolDemo(5, 10);

for (int i = 0; i < 20; i++) {
    final int index = i;
    threadPool.execute(() -> {
        System.out.println("执行任务" + index);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
}

threadPool.shutdown();

在示例中我们创建了一个线程池,包含5个工作线程和一个容量为10的任务队列。我们通过循环向线程池中提交20个任务,每个任务打印执行的编号,并暂停2秒。最后调用shutdown方法来关闭线程池。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一文探究ArrayBlockQueue函数及应用场景 - Python技术站

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

相关文章

  • Java下SpringBoot创建定时任务详解

    下面我将为您详细讲解“Java下SpringBoot创建定时任务详解”的完整攻略。 SpringBoot定时任务详解 什么是定时任务 定时任务指定在特定的时间段执行的一种操作,比如每天凌晨1点执行一次数据库备份操作、每分钟执行一次数据同步操作等。在开发中,经常使用定时任务来完成一些需要定期执行的任务。 SpringBoot中创建定时任务 SpringBoot…

    Java 2023年5月19日
    00
  • Springboot连接数据库及查询数据完整流程

    下面我将为大家详细讲解“Springboot连接数据库及查询数据完整流程”的完整攻略。 准备工作 首先,需要在pom.xml文件中添加以下依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-st…

    Java 2023年5月20日
    00
  • springMVC拦截器HandlerInterceptor用法代码示例

    下面详细讲解一下“springMVC拦截器HandlerInterceptor用法代码示例”的完整攻略。 什么是HandlerInterceptor? HandlerInterceptor是Spring MVC框架的拦截器,用于在controller处理请求之前和之后进行一些额外的处理。HandlerInterceptor是一个接口,需要自定义实现它,并将其…

    Java 2023年5月31日
    00
  • Java方法的返回值及注意事项小结

    当我们在编写Java程序时,有时需要从方法中获取数据。在许多情况下,我们希望方法能够返回一个值,这就是Java方法的返回值。在本文中,将介绍Java方法的返回值以及注意事项。 什么是Java方法的返回值? Java方法的返回值是指当方法被调用时,此方法所返回的数据。方法的返回值用于与另一个方法或代码交互。一般情况下,Java方法返回值可以是任何基本数据类型(…

    Java 2023年5月26日
    00
  • 详解Java基础知识——JDBC

    详解Java基础知识——JDBC JDBC的介绍 JDBC(Java Database Connectivity)是Java语言中用于操作关系型数据库的API,通过JDBC可以实现Java与数据库之间的交互。JDBC主要包含以下几个部分: DriverManager:驱动管理器,用于管理各种数据库驱动。 Connection:连接对象,用于与数据库建立连接。…

    Java 2023年5月19日
    00
  • 深入解析Java的Servlet过滤器的原理及其应用

    深入解析Java的Servlet过滤器的原理及其应用 什么是Servlet过滤器 Servlet过滤器是Java Web开发中常用的一种技术,通过在Web应用中设置过滤器,可以在请求和响应之间添加特定的逻辑。Servlet过滤器可以对请求和响应进行拦截、修改或增强,可以实现对访问控制、安全验证、日志记录、数据压缩等的功能。 Servlet过滤器的工作原理和应…

    Java 2023年6月15日
    00
  • Spring Boot应用开发初探与实例讲解

    Spring Boot应用开发初探与实例讲解 什么是Spring Boot? Spring Boot是由Spring官方推出的一款快速构建spring应用程序的框架。它简化了Spring应用程序的开发和部署过程,提供了许多默认配置和开箱即用的组件,使得开发者能够更加专注于业务逻辑的编写。 如何开始Spring Boot应用开发? 步骤一:环境准备 首先,我们…

    Java 2023年5月19日
    00
  • 利用python分析access日志的方法

    当我们需要了解一个网站的访问情况时,经常会使用access日志来进行分析。在本文中,我们将利用python来分析access日志。 准备工作 在开始之前,我们需要一些准备工作: 确认access日志的格式是否符合Nginx的常规格式,通常情况下,access日志应该包括如下信息: 远程访问IP 访问时间 请求方式 请求的URL 请求的HTTP协议版本 请求的…

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