- 为什么要用线程池
- 线程池原理
- 线程池API
1 为什么要用线程池
- 线程在jvm中是一个对象,更是操作系统的资源,线程创建或销毁都伴随开销,如果创建时间+销毁时间>执行时间,就会不合理
- 对象是占用堆空间,操作系统线程占用系统资源,根据java虚拟机规范,一个线程默认允许占用的最大栈空间为1M,而栈空间是从系统内存分配的,如果开辟的线程太多,将会消耗大量内存
- 操作系统需要频繁切换线程上下文,会影响性能
线程不是越多越好,线程池的推出,就是为了方便控制线程数量,合理利用资源,提高资源利用率
2 线程池原理
- 概念
- 任务execute过程
2.1 概念
任务队列:用于存放没有处理的任务,提供缓存机制和拒绝策略。
工作线程:线程池中的线程,在没有任务执行时处于等待状态,可以循环执行任务。
线程池管理器:用于创建并管理线程池,包括创建线程池、销毁线程池和添加新任务。
任务接口:每个任务都必须实现的接口,以供工作线程调度执行,主要规定了任务的入口、任务执行后的收尾工作及任务的执行状态。
2.2 任务execute过程
- 过来一个新任务,如果没有达到核心线程数,则新建线程执行该新任务;
- 否则放入工作队列,若队列已满,则判断是否达到最大线程数;
- 若未达到最大线程数,则新建线程,否则执行拒绝策略;
- 若线程数超过最大线程数,线程空闲时会将线程终止;
- 若线程数未超过最大线程数,但设置了线程存活时间,则超过时间线程也会被终止
3 线程池API
- 接口定义和实现类
- 方法定义
- Executors工具类
3.1 接口定义和实现类
类型 | 名称 | 描述 |
---|---|---|
接口 | Executor | 最上层的接口,定义了执行任务的execute方法 |
接口 | ExecutorService | 继承了Executor接口,拓展了Callable、Future、关闭方法 |
接口 | ScheduledExecutorService | 继承了ExecutorService接口,拓展了定时任务相关的方法 |
实现类 | ThreadPoolExecutor | 基础、标准的线程池实现 |
实现类 | ScheduledThreadPoolExecutor | 拓展了定时任务相关的方法 |
3.2 方法定义
//---ExecutorService---
//监测线程池是否已经关闭,直到所有任务完成或发生超时或当前线程被中断
awaitTermination(long timeout, TimeUnit unit)
//执行给定的任务集合,执行完毕后,返回结果
invokeAll(Collection<? extends Callable<T>> tasks)
//执行给定的任务集合,任意执行一个成功则返回结果,其它任务终止
invokeAny(Collection<? extends Callable<T>> tasks)
//如果线程池已关闭,则返回true
isShutdown()
//如果关闭后所有任务都已完成,则返回true
isTerminated()
//优雅关闭线程池,之前提交的任务将被执行,但不会接受新任务
shutdown()
//尝试停止所有正在执行的任务,停止等待任务的处理,并返回等待执行任务列表
shutdownNow()
//提交一个用于执行的Callable任务,并返回一个Future,用于获取Callable执行结果
submit(Callable<T> task)
//---ScheduledExecutorService---
schedule(Callable<V> callable, long delay, TimeUnit unit)
schedule(Runnable command, long delay, TimeUnit unit)
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
以上方法会创建并执行一个周期性任务,过了初始延迟时间,第一次被执行,若一次任务执行时间超过周期时间,scheduleAtFixedRate会在任务执行结束后,立刻执行,而scheduleWithFixedDelay会在结束的时间基础上,计算执行延时。
3.3 Executors工具类
newFixedThreadPool(int nThreads)
创建一个固定大小、无界任务队列的线程池(核心线程数=最大线程数)
newCachedThreadPool()
创建一个大小无界的缓存线程池,工作队列为同步队列,线程空闲超过60s将被销毁释放(核心线程数为0,最大线程数为Integer.MAX_VALUE),线程数随任务数发生变化,适用于执行耗时较小的异步任务
newSingleThreadExecutor()
创建只有一个线程、无界任务队列的线程池,适用于确保任务按加入顺序依次执行的场景,无需担心线程执行异常任务中止。
newScheduledThreadPool(int corePoolSize)
能定时执行任务的线程池(核心线程数由参数决定,最大线程数为Integer.MAX_VALUE)
参考文章
结语
本人所有博客仅用于学习记录,不做任何商业用途,如涉及侵权,还请联系删除,感谢阅读,欢迎留言,一起进步~