Java线程池ThreadPoolExecutor原理及使用实例

  

Java线程池ThreadPoolExecutor原理及使用实例

1. 线程池ThreadPoolExecutor的工作原理

线程池ThreadPoolExecutor是Java中常用的一个多线程处理工具。其主要特点是在应用程序启动时预先创建线程池中的一定数量的线程,在应用程序运行时,将需要执行的任务放到线程池中,线程池中的线程依次执行这些任务。线程池负责监控线程的创建和销毁,以及负责分发任务给线程。

ThreadPoolExecutor是JDK提供的线程池实现,其构造函数的参数非常多,一般的使用方式如下:

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
  • corePoolSize:线程池中所保存的核心线程数,包括空闲线程。当提交一个任务后,若线程池中核心线程的数量少于corePoolSize,即使此时有空闲线程,也会创建一个新的线程来处理任务。当提交任务的频率超过线程池能处理的数量时,若加上新提交的任务,所有线程都加入工作队列中,而工作队列长度已达到最大长度,则线程池就会启动maximumPoolSize- corePoolSize个线程来处理任务。
  • maximumPoolSize:线程池中允许的最大线程数。当工作队列已满并且无法继续添加任务时,线程池会启动maximumPoolSize-corePoolSize个线程来处理任务。
  • keepAliveTime:当线程池中的空闲线程数量大于corePoolSize时,这些空闲线程能存活的最长时间(单位为unit)。
  • unit:keepAliveTime的时间单位。
  • workQueue:用于保存等待执行的任务的阻塞队列。
  • threadFactory:用于创建新线程的工厂。
  • handler:当线程池中的队列和最大线程池都已经满时,执行的拒绝策略。

2. 线程池ThreadPoolExecutor的使用实例

下面分别给出使用线程池ThreadPoolExecutor实现两种常见场景的示例。

2.1 示例1:实现多个任务的并行处理

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

public class ParallelTasksProcessor {

    private ExecutorService executorService;

    public ParallelTasksProcessor() {
        //初始化具有10个线程的线程池
        executorService = Executors.newFixedThreadPool(10);
    }

    public void submitTask(Runnable task) {
        //提交任务
        executorService.submit(task);
    }

    public void shutDown() {
        //关闭线程池
        executorService.shutdown();
    }
}

  • 初始化线程池时设置线程数为10个。
  • 在执行任务时将任务传递给线程池,并由线程池负责执行任务。
  • 关闭线程池时调用ExecutorService的shutdown()方法。

2.2 示例2:实现大量任务的序列化处理

import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class SequenceTasksProcessor {

    private ThreadPoolExecutor executor;

    public SequenceTasksProcessor() {
        //初始化具有2个线程的线程池
        executor = new ThreadPoolExecutor(2, 2, 0L, TimeUnit.MILLISECONDS,
                new PriorityBlockingQueue<Runnable>());
    }

    public void submitTask(Callable task) {
        FutureTask futureTask = new FutureTask(task);
        //提交任务
        executor.submit(futureTask);
    }

    public void shutDown() {
        //关闭线程池
        executor.shutdown();
    }
}

  • 初始化线程池时设置线程数为2个、使用PriorityBlockingQueue优先级阻塞队列。
  • 在执行任务时将任务传递给线程池,由线程池负责执行任务。
  • 使用FutureTask对Callable进行封装,以便获取到任务执行结果。
  • 关闭线程池时调用ThreadPoolExecutor的shutdown()方法。

3. 总结

Java线程池ThreadPoolExecutor作为一种高效的多线程处理工具,可以在并发处理场景中发挥重要作用。在使用ThreadPoolExecutor时,需要了解其主要参数设置以及使用方式,并且注意在程序结束时显式关闭线程池,避免资源浪费。同时,还需要关注线程池中线程的数量是否过多或过少,合理地调整线程池中线程的数量,以提高程序的性能和稳定性。

相关文章