ThreadPool线程池是Java多线程并发编程非常重要的技能,下面就重点来详解ThreadPool线程池@mikechen
Thread Pool线程池定义
Thread Pool,翻译过来就是线程池,主要通过池化思想管理线程的工具,用于管理和调度线程。
ThreadPool线程池作用
通过使用线程池,可以减少线程的创建和销毁开销,避免线程过多导致资源耗尽的问题,同时还能更好地管理并发任务的执行。
ThreadPool线程池配置
Thread Pool线程池配置参数,主要包含如下7大参数
ThreadPoolExecutor threadPool = new ThreadPoolExecutor( corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue, handler);
参数说明:
corePoolSize
:核心线程数,指的是线程池中一直存在的线程数量。maximumPoolSize
:最大线程数,指的是线程池中允许的最大线程数量,包括核心线程和非核心线程。keepAliveTime
:非核心线程的空闲时间,超过这个时间,空闲线程会被销毁。workQueue
:任务队列,用于存储等待执行的任务。threadFactory
:用于创建线程的工厂。rejectedExecutionHandler
:拒绝策略,指定当任务队列已满且线程池达到最大线程数时如何处理新任务。
ThreadPool线程池原理
ThreadPool线程池的工作原理,如下图所示:
线程池的工作流程如下:
1.检查线程池是否已满
如果线程池中的线程数小于 corePoolSize
,则创建新线程来执行任务。
2.将任务放入队列
如果线程池中的线程数大于等于 corePoolSize
,则将任务放入任务队列,直到有空闲的线程可用。
3.准备开始处理任务
当一个线程完成了任务的执行后,它会返回线程池,并且准备处理下一个任务。
4.如果已满执行拒绝策略
如果线程池中的线程数量已经达到了限制,而且任务队列已经满了,那么线程池会拒绝该任务并执行拒绝策略。
如下图所示:
更加详细的拒绝策略,请查看:Java线程池拒绝策略详解(4种常见拒绝策略)
ThreadPool线程池创建
ThreadPool线程池创建,如要包含如下几种:
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面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》