1、ThreadPoolExecutor 的类关系
1、1 举例说明
-
Java线程池就像一个公司里的员工,公司
最多容纳人数是最大线程数,这个公司有固定数量的员工(核心线程数),但是可以招临时外包(最大线程数减去核心数)。有一个待执行的任务清单看板(工作队列)。线程空闲时间就是外包员工多久没活就请走。 -
来活了来活了,首先把活给固定员工,然后固定员工手上都有活,就放到任务清单看板上,都塞满了。只能招点临时外包干。如果还是满了就看拒绝策略了。
-
拒绝策略有- (1)AbortPolicy:直接抛出异常,默认策略;
- (2)CallerRunsPolicy:用调用者所在的线程来执行任务;
- (3)DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;
- (4)DiscardPolicy:直接丢弃任务;
-
使用Java线程池的好处是,公司可以更好地管理员工和任务,避免员工过多或者任务过多的情况,提高工作效率。同时,因为员工不是每次都需要重新招聘,所以公司的成本也会降低。
1、2 代码和图解
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // corePoolSize
10, // maximumPoolSize
60, // keepAliveTime
TimeUnit.SECONDS, // time unit for keepAliveTime
new ArrayBlockingQueue<Runnable>(10), // work queue
new ThreadPoolExecutor.DiscardPolicy() // rejection policy
);
1、3 提交任务
- execute 方法不要方返回值,不知道是否执行成功。
- submit 会返回Future类型,
- mFuture.get()会阻塞直到任务完成。
- mFuture.get(1000,TimeUnit.SECONDS)会阻塞直到任务完成,如果时间到了任务没跑完依旧会返回
Future<?> mFuture = executor.submit(t);
mFuture.get();
mFuture.get(100000,TimeUnit.SECONDS);
1、4 关闭线程
- shutdown:将线程池设置为SHUTDOWN状态,让它不再接收新任务。
- shutdownNow:将线程池设置为STOP状态,不再接收新装填,并向执行和暂停中的线程执行interrupt方法。interrupt方法不直接停止。
- interrupt方法线程内有InterruptedException或者Exception才能中断成功
- 会返回所有所有没有正在执行任务的线程。
List<Runnable> runnables = executor.shutdownNow();
1、5 合理配置线程池
-Runtime.getRuntime().availableProcessors()获取CPU个数N
- CPU密集型: 配置N+1
- IO密集型:配置2N
2、线程池种类
看下我的代码运行一下就知道了 JavaDemo/src/main/java/com/example/javademo/thread/threadpool · wangxiangqi/JavaStudyDemo - 码云 - 开源中国 (gitee.com)
| 类型 | 别名 | 池内线程 | 特点 | 场景 | |
|---|---|---|---|---|---|
| FixedThreadPool | 定长线程池 | 核心线程和最大线程一样多 | 1、核心线程空闲也不会回收除非被关闭。 2、当线程都在干活,其余任务会待在阻塞队列。知道有线程空闲出来。 3、任务是无界的LinkedBlockingQueue | 控制线程最大并发数 | new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); |
| CachedThreadPool | 可缓存线程池 | 核心线程为0,最大线程数为int最大值 | 1、优先利用闲置处理新任务 2、无线程就新建 3、闲置超过一分钟才回收 | 执行数量多耗时少的任务 | new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue()); |
| ScheduledThreadPool | 定时线程池 | 核心线程为传入值,非核心线程为int最大值 | 1、非核心线程闲置时会立马回收 | 指定定时/周期性任务 | super(corePoolSize, 2147483647, 10L, TimeUnit.MILLISECONDS, new ScheduledThreadPoolExecutor.DelayedWorkQueue()); |
| SingleThreadExecutor | 单线程池 | 核心和最大都是1 | 1、保证所有任务按照顺序在一个线程中执行 2、不需要处理线程同步问题 | 单线程 | return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue())); |