寒假打卡04_1月16日

Java 线程池的使用——ExecutorService 和 ThreadPoolExecutor 解析

在多线程编程中,线程池是一种非常重要的工具。它能够有效地管理和复用线程资源,从而提高程序的性能和响应速度。在本篇文章中,我们将详细探讨 Java 中的线程池概念,并介绍 ExecutorServiceThreadPoolExecutor 的使用方法。

线程池的概念

线程池是一种线程管理机制,它预先创建了一定数量的线程,并将其放入池中。通过这种方式,程序可以重复利用这些线程,而不需要频繁地创建和销毁线程,从而减少了系统资源的消耗。

使用线程池的好处包括:

  • 降低线程创建和销毁的开销
  • 提高响应速度
  • 有效控制并发线程的数量,避免资源过度消耗

Executor 框架

Java 从 java.util.concurrent 包开始引入了 Executor 框架,它提供了一套用于并发编程的标准 API。其中,ExecutorServiceThreadPoolExecutor 是两个非常重要的接口和类。

ExecutorService

ExecutorService 是一个高级接口,定义了一组方法来管理终止和跟踪异步任务的执行。我们可以通过调用 Executors 工具类的静态方法来创建 ExecutorService 实例,例如 newFixedThreadPoolnewCachedThreadPoolnewSingleThreadExecutor 等。

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

public class ExecutorServiceDemo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        for (int i = 0; i < 5; i++) {
            executorService.submit(() -> {
                System.out.println(Thread.currentThread().getName() + " is running");
            });
        }

        executorService.shutdown();
    }
}

在上述代码中,我们创建了一个固定大小为 3 的线程池,并提交了 5 个任务。线程池中的线程将依次执行这些任务。

ThreadPoolExecutor

ThreadPoolExecutorExecutorService 的一个实现类,它提供了更为灵活和强大的线程池功能。我们可以通过其构造方法来创建定制化的线程池。

import java.util.concurrent.*;

public class ThreadPoolExecutorDemo {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2, // corePoolSize
            4, // maximumPoolSize
            60, // keepAliveTime
            TimeUnit.SECONDS, // keepAliveTime unit
            new ArrayBlockingQueue<>(2), // workQueue
            new ThreadPoolExecutor.AbortPolicy() // handler
        );

        for (int i = 0; i < 6; i++) {
            executor.submit(() -> {
                System.out.println(Thread.currentThread().getName() + " is running");
            });
        }

        executor.shutdown();
    }
}

在上述代码中,我们创建了一个 ThreadPoolExecutor 实例,并设置了核心线程数为 2、最大线程数为 4、线程空闲时间为 60 秒、工作队列为 ArrayBlockingQueue、拒绝策略为 AbortPolicy。我们提交了 6 个任务,线程池中的线程将依次执行这些任务。

线程池的拒绝策略

当线程池的工作队列已满且没有空闲线程时,线程池需要采取一定的策略来处理新提交的任务。ThreadPoolExecutor 提供了以下几种拒绝策略:

  • AbortPolicy:直接抛出 RejectedExecutionException 异常,默认策略
  • CallerRunsPolicy:由调用线程执行该任务
  • DiscardPolicy:直接丢弃任务,不予处理
  • DiscardOldestPolicy:丢弃最旧的未处理任务,然后重新提交新任务

我们可以在创建 ThreadPoolExecutor 时通过构造方法的 handler 参数来指定拒绝策略。

示例代码

以下是一个使用 ExecutorServiceThreadPoolExecutor 的示例代码,展示了如何创建和管理线程池:

import java.util.concurrent.*;

public class ThreadPoolExample {
    public static void main(String[] args) {
        // 创建一个固定大小的线程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        submitTasks(fixedThreadPool);

        // 创建一个自定义的线程池
        ThreadPoolExecutor customThreadPool = new ThreadPoolExecutor(
            2, 4, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), new ThreadPoolExecutor.CallerRunsPolicy()
        );
        submitTasks(customThreadPool);
    }

    private static void submitTasks(ExecutorService executorService) {
        for (int i = 0; i < 5; i++) {
            executorService.submit(() -> {
                System.out.println(Thread.currentThread().getName() + " is executing task");
            });
        }
        executorService.shutdown();
    }
}

在上述代码中,我们创建了一个固定大小的线程池和一个自定义的线程池,并向它们提交了任务。线程池中的线程将依次执行这些任务。

总结

线程池是多线程编程中非常重要的工具,它能够有效地管理和复用线程资源,从而提高程序的性能和响应速度。Java 提供了 ExecutorServiceThreadPoolExecutor 等类来实现线程池功能。通过使用这些类,我们可以轻松地创建和管理线程池,确保程序的高效运行。

希望通过本篇文章,大家对 Java 线程池的使用有了更深入的了解。在接下来的文章中,我们将继续探讨更多关于 Java 多线程的知识点,敬请期待!

posted @ 2025-01-16 09:08  aallofitisst  阅读(13)  评论(0)    收藏  举报