ThreadPool线程池详解(看这篇就够了)

ThreadPool线程池详解(看这篇就够了)-mikechen

ThreadPool线程池是Java多线程并发编程非常重要的技能,下面就重点来详解ThreadPool线程池@mikechen

Thread Pool线程池定义

Thread Pool,翻译过来就是线程池,主要通过池化思想管理线程的工具,用于管理和调度线程。

 

ThreadPool线程池作用

通过使用线程池,可以减少线程的创建和销毁开销,避免线程过多导致资源耗尽的问题,同时还能更好地管理并发任务的执行。

 

ThreadPool线程池配置

Thread Pool线程池配置参数,主要包含如下7大参数

ThreadPool线程池详解(看这篇就够了)-mikechen

ThreadPoolExecutor threadPool = new ThreadPoolExecutor( corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue, handler);

参数说明:

  • corePoolSize:核心线程数,指的是线程池中一直存在的线程数量。
  • maximumPoolSize:最大线程数,指的是线程池中允许的最大线程数量,包括核心线程和非核心线程。
  • keepAliveTime:非核心线程的空闲时间,超过这个时间,空闲线程会被销毁。
  • workQueue:任务队列,用于存储等待执行的任务。
  • threadFactory:用于创建线程的工厂。
  • rejectedExecutionHandler:拒绝策略,指定当任务队列已满且线程池达到最大线程数时如何处理新任务。

 

ThreadPool线程池原理

ThreadPool线程池的工作原理,如下图所示:

ThreadPool线程池详解(看这篇就够了)-mikechen

线程池的工作流程如下:

1.检查线程池是否已满

如果线程池中的线程数小于 corePoolSize,则创建新线程来执行任务。

2.将任务放入队列

如果线程池中的线程数大于等于 corePoolSize,则将任务放入任务队列,直到有空闲的线程可用。

3.准备开始处理任务

当一个线程完成了任务的执行后,它会返回线程池,并且准备处理下一个任务。

4.如果已满执行拒绝策略

如果线程池中的线程数量已经达到了限制,而且任务队列已经满了,那么线程池会拒绝该任务并执行拒绝策略。

如下图所示:

ThreadPool线程池详解(看这篇就够了)-mikechen

更加详细的拒绝策略,请查看:Java线程池拒绝策略详解(4种常见拒绝策略)

 

ThreadPool线程池创建

ThreadPool线程池创建,如要包含如下几种:

ThreadPool线程池详解(看这篇就够了)-mikechen

1.FixedThreadPool(固定大小线程池)

如下所示:

ExecutorService executor = Executors.newFixedThreadPool(5);

该线程池维护一个固定数量的线程,在提交的任务数超过线程池大小时,任务会在队列中等待,适用于需要限制线程数量的场景。

 

2.SingleThreadPool(单线程池)

如下所示:

ExecutorService executor = Executors.newSingleThreadExecutor();

该线程池只包含一个线程,在该线程中按顺序执行提交的任务。适用于需要保证任务按顺序执行的场景。

 

3.CachedThreadPool(缓存线程池)

如下所示:

ExecutorService executor = Executors.newCachedThreadPool();

该线程池允许创建多个线程来处理任务,如果线程池中有空闲线程可用,则会重用它们,否则会创建新的线程。适用于有大量短期任务的场景。

 

4.ScheduledThreadPool(调度线程池)

该线程池用于执行定时任务或延迟任务。

如下所示:

ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
executor.schedule(new MyTask(1), 5, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(new MyTask(2), 1, 5, TimeUnit.SECONDS);
executor.shutdown();

这个线程池就是为了定时而发明的,它支持定时或周期性执行任务,比如:10秒钟执行一次任务。

 

6.WorkStealingPool(工作窃取线程池)

该线程池使用一种工作窃取算法,允许空闲线程从忙碌线程队列中窃取任务,从而提高线程的利用率。

如下所示:

ExecutorService executor = Executors.newWorkStealingPool();
for (int i = 0; i < 10; i++) {
    executor.execute(new MyTask(i));
}
executor.shutdown();

适用于计算密集型任务。

 

7.最原始的创建线程池的⽅式

可以通过ThreadPoolExecutor 手动创建线程池,这也是阿里等大厂推荐使用方式。

 

ThreadPool线程池使用

下面是一个简单的Java线程池创建示例:

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

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

        for (int i = 0; i < 10; i++) {
            final int taskNumber = i;
            executor.submit(() -> {
                System.out.println("Task " + taskNumber + " executed by " + Thread.currentThread().getName());
            });
        }

        executor.shutdown(); // 关闭线程池
    }
}

在上述示例中,通过 Executors.newFixedThreadPool(5) 创建了一个固定大小为 5 的线程池。

然后,通过 submit 方法提交了10个任务,线程池会自动管理线程的创建、执行和销毁。

最后,通过 executor.shutdown() 关闭线程池。

以上就是ThreadPool线程池的详解,希望对你掌握Java线程池有所帮助!

陈睿mikechen

十余年BAT架构经验,资深技术专家,就职于阿里、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法