Java多线程ThreadPoolExecutor详解

Java多线程ThreadPoolExecutor详解

ThreadPoolExecutor 是 Java 中常用的线程池实现类,通过线程池可以更好地使用资源,提高程序性能。本文将详细讲解 ThreadPoolExecutor 的使用,包括线程池的创建、使用和销毁等方面。

线程池的创建

线程池是通过 ThreadPoolExecutor 类创建的,构造方法有几个重载,可以根据需求选择使用。

常用构造方法

public ThreadPoolExecutor(int corePoolSize, 
                           int maximumPoolSize, 
                           long keepAliveTime, 
                           TimeUnit unit, 
                           BlockingQueue<Runnable> workQueue)

该构造方法是最常用的,它会创建一个新的线程池对象,其中:

  • corePoolSize:核心线程数,即线程池中最少会保持的活跃线程数。
  • maximumPoolSize:最大线程数,即线程池中最多会同时存在的线程数。
  • keepAliveTime:线程空闲时间,超过该时间的线程会被销毁。
  • TimeUnit:时间单位,用于指定时间的单位,如 TimeUnit.SECONDS 为秒。
  • BlockingQueue<Runnable>:任务队列,用于存储线程池中等待执行的任务。

其他构造方法

还有其他的构造方法,包括使用默认参数创建线程池的无参构造方法、可以指定线程工厂的构造方法、可以指定拒绝策略的构造方法等。这里不做详细说明,可参考官方文档。

线程池的使用

线程池创建完成之后,下一步是将任务提交到线程池中执行。有三种提交任务的方法:`

execute() 方法

execute() 方法用于异步提交一个任务,提交后立即返回,不会等待任务执行完成,示例如下:

ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(() -> {
    System.out.println("Task 1 is running.");
});

submit() 方法

submit() 方法除了异步提交任务,还会返回一个 Future 实例,可以通过它获取任务的执行结果,示例如下:

ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> future = executor.submit(() -> {
    System.out.println("Task 1 is running.");
    return "Task 1";
});
System.out.println(future.get()); // 输出:Task 1

invokeAll() 方法

invokeAll() 方法用于批量提交任务,并等待所有任务执行完成,示例如下:

ExecutorService executor = Executors.newFixedThreadPool(2);
List<Callable<String>> tasks = new ArrayList<>();
tasks.add(() -> {
    System.out.println("Task 1 is running.");
    return "Task 1";
});
tasks.add(() -> {
    System.out.println("Task 2 is running.");
    return "Task 2";
});
List<Future<String>> futures = executor.invokeAll(tasks);
futures.forEach(future -> {
    try {
        System.out.println(future.get());
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
});

线程池的销毁

线程池有两种销毁方法,分别是 shutdown()shutdownNow()

shutdown() 方法

调用 shutdown() 方法后,线程池会尝试将等待执行的任务全部执行完毕,不再接受新的任务提交,示例如下:

ExecutorService executor = Executors.newFixedThreadPool(2);
executor.shutdown();

shutdownNow() 方法

调用 shutdownNow() 方法后,线程池会立即关闭,不会等待等待执行的任务全部执行完毕,示例如下:

ExecutorService executor = Executors.newFixedThreadPool(2);
executor.shutdownNow();

除此之外,还可以通过其他方法获取线程池状态、设置线程池大小、修改拒绝策略等等。

示例说明

下面是两条使用 ThreadPoolExecutor 的示例说明。

示例一

有一个消息队列,需要不断地往队列中插入消息,同时有多个工作线程从队列中读取消息并进行处理。为了避免每次都创建线程,我们可以使用线程池来管理这些工作线程。具体实现如下:

public class MessageQueue {
    private BlockingQueue<String> queue = new LinkedBlockingQueue<>();
    private ThreadPoolExecutor executor = new ThreadPoolExecutor(
            5, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100));

    public void addMessage(String message) {
        queue.add(message);
    }

    public void start() {
        while (true) {
            try {
                String message = queue.take();
                executor.execute(() -> {
                    // 处理消息
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void stop() {
        executor.shutdownNow();
    }
}

该示例使用 BlockingQueue 存储消息,使用 ThreadPoolExecutor 管理工作线程。在 start() 方法中,通过 BlockingQueue 不断地从队列中提取消息并将其作为任务提交到线程池中执行。在 stop() 方法中,调用 shutdownNow() 方法关闭线程池。

示例二

有一个需要处理的任务列表,需要多个工作线程并发处理,每一个任务的执行时间都不一样。为了使用多个线程并发执行任务,我们可以使用线程池来管理这些工作线程。具体实现如下:

public class TaskList {
    private List<Task> taskList = new ArrayList<>();
    private ThreadPoolExecutor executor = new ThreadPoolExecutor(
            3, 6, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100));

    public void addTask(Task task) {
        taskList.add(task);
    }

    public void start() {
        CountDownLatch latch = new CountDownLatch(taskList.size());
        List<Future<?>> futures = new ArrayList<>();
        for (Task task : taskList) {
            futures.add(executor.submit(() -> {
                try {
                    task.execute();
                } finally {
                    latch.countDown();
                }
            }));
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        futures.forEach(future -> {
            try {
                future.get();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        });
    }

    public void stop() {
        executor.shutdownNow();
    }
}

该示例使用 List 存储任务列表,使用 ThreadPoolExecutor 管理工作线程。在 start() 方法中,通过 ExecutorService 提交每一个任务到线程池中执行,并使用 CountDownLatch 检测所有任务是否执行完毕。在 stop() 方法中,调用 shutdownNow() 方法关闭线程池。

以上就是 ThreadPoolExecutor 的详细使用攻略,包括线程池的创建、使用和销毁等方面,并提供了两个示例说明。希望对您有所帮助。

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

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

相关文章

  • Java并发线程之线程池的知识总结

    Java并发线程之线程池的知识总结 线程池的概念 线程池是一种线程使用模式。线程池中包含了一组线程,线程池可以用来控制创建线程的数量和频率,降低了系统资源消耗率。当有新任务需要执行时,可以直接使用已经存在线程,而不是重新创建新的线程。 线程池的用途 线程池的主要作用是:* 重用线程* 控制线程数量,避免线程数量过多,导致系统资源的消耗和浪费* 提高线程的创建…

    多线程 2023年5月16日
    00
  • springboot tomcat最大线程数与最大连接数解析

    下面是“Spring Boot Tomcat最大线程数与最大连接数解析”的攻略。 一、Tomcat的最大连接数和最大线程数是什么? Tomcat是一个Web服务器,默认情况下,它的连接请求都是使用HTTP/1.1协议的。Tomcat的最大连接数指的是能同时建立的最大连接数,而Tomcat的最大线程数指的是Tomcat处理请求的最大线程数量。这两个参数可以决定…

    多线程 2023年5月17日
    00
  • java多线程应用实现方法

    Java多线程应用实现方法 什么是多线程 多线程是指程序中同时存在多个线程执行不同的任务。在Java中,每个线程都是一个单独的执行流程,每个线程都拥有自己的栈空间和执行上下文。 为什么需要使用多线程 在某些场景下,使用多线程能够提高程序的运行效率和响应速度。举例来说,当一个程序需要从网络上下载文件时,若使用单线程实现,则下载完一个文件后才会开始下载下一个文件…

    多线程 2023年5月17日
    00
  • 在IntelliJ IDEA中多线程并发代码的调试方法详解

    当我们在编写多线程并发代码时,调试代码通常比调试单线程代码更为困难。但是,在使用 IntelliJ IDEA 这样的 IDE 中,我们可以利用 IDE 的一些工具来帮助我们更有效地调试多线程并发代码。本文将具体介绍在 IntelliJ IDEA 中如何调试多线程并发代码的步骤和方法。 调试多线程并发代码的步骤 针对我们要调试的类,打开 IntelliJ ID…

    多线程 2023年5月16日
    00
  • 并发编程ConcurrentLinkedQueue示例详解

    下面是“并发编程ConcurrentLinkedQueue示例详解”的完整攻略: 并发编程ConcurrentLinkedQueue示例详解 什么是ConcurrentLinkedQueue ConcurrentLinkedQueue是Java的一个并发工具类,它提供了线程安全的队列操作。与LinkedList不同,ConcurrentLinkedQueue…

    多线程 2023年5月16日
    00
  • 详解C语言编程之thread多线程

    详解C语言编程之thread多线程 什么是多线程编程? 多线程编程是指同时运行多个线程的程序设计,一个进程可包含多个线程,同时执行多个线程可以提升程序的性能和效率。 C语言的多线程实现 C语言的多线程实现一般通过线程库来实现。在Linux下常用的线程库有pthread。Windows下常用的线程库有Win32 API和C++11的thread库。pthrea…

    多线程 2023年5月17日
    00
  • PHP 异步执行方法,模拟多线程的应用分析

    下面是关于“PHP 异步执行方法,模拟多线程的应用分析”的完整攻略: 什么是PHP异步执行? 在PHP脚本执行时,通常是按照顺序执行的,即一行一行顺序执行。这就意味着,在执行一个比较耗时的操作时,脚本会被阻塞,等待操作完成之后再继续执行下一行代码。这种方式叫做同步执行。 异步执行就是一种不阻塞当前线程的执行方式,在操作耗时完成之前,程序能够继续执行下一行代码…

    多线程 2023年5月17日
    00
  • 解决SpringBoot内嵌Tomcat并发容量的问题

    问题描述: 在使用SpringBoot内嵌Tomcat时,如果并发请求量较大,Tomcat容易出现瓶颈,导致服务响应延迟或崩溃。 解决方案: 通过配置Tomcat的线程池和连接器等参数,来提高Tomcat的并发处理能力。 步骤说明: 在SpringBoot应用的配置文件中,添加Tomcat的线程池配置 server: tomcat: max-threads:…

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