线程池的概念与数据库连接池的概念基本相似,线程池是为了控制线程的数量;
线程是java中的一个对象,频繁的创建和销毁线程,都将消耗时间,降低程序的执行效率;过多的线程也将加速堆栈控件的消耗;更多的线程会导致操作系统频繁切换线程的上下文,拖慢系统的性能。
线程池的内容:
1、线程池管理器:用于创建并管理线程池;
2、工作线程:线程池中的线程,循环执行线程池中的任务,没有任务则处于等待状态;
3、任务接口:规定了任务的入口、任务结束后的操作、任务状态等;是线程池中任务必须实现的接口,供工作线程调用;
4、任务队列:待执行的任务列表;
接口及实现类:
类型 | 名称 | 描述 |
---|---|---|
接口 | Executor | 定义执行任务的方法excute |
接口 | ExecutorService | 继承Executor接口,扩展Callable、Future、关闭方法 |
接口 | ScheduledExecutorService | 继承ExecutorService,添加定时任务相关的方法 |
实现类 | ThreadPoolExecutor | 基础的线程池实现类 |
实现类 | ScheduledThreadPoolExecutor | 继承ThreadPoolExecutor,实现了ScheduledExecutorService中定时任务相关的方法 |
ExecutorService中的方法:
ScheduledThreadPoolExecutor中的方法:
第三个和第四个区别在于任务执行时间超过周期时间时,第三个会在上次任务执行结束后,立即执行下次任务,第四个在上次任务执行结束后,继续间隔周期时间进行执行。
线程池任务的执行过程:
演示代码:
核心线程数量5,最大数量10,无界队列,超出核心线程数量的线程存活时间:5秒, 无指定拒绝策略的
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
new LinkedBlockingQueue());
核心线程数量5,最大数量10,队列大小3,超出核心线程数量的线程存活时间:5秒, 指定拒绝策略
// 创建一个 核心线程数量为5,最大数量为10,等待队列最大是3 的线程池,也就是最大容纳13个任务。
// 默认的策略是抛出RejectedExecutionException异常,java.util.concurrent.ThreadPoolExecutor.AbortPolicy
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
new LinkedBlockingQueue(3), new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.err.println("有任务被拒绝执行了");
}
});
核心线程数量5,最大数量5,无界队列,超出核心线程数量的线程存活时间:0秒
// 和Executors.newFixedThreadPool(int nThreads)一样的
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
核心线程数量0,最大数量Integer.MAX_VALUE,SynchronousQueue队列,超出核心线程数量的线程存活时间:60秒
SynchronousQueue,实际上它不是一个真正的队列,因为它不会为队列中元素维护存储空间。与其他队列不同的是,它维护一组线程,这些线程在等待着把元素加入或移出队列。
在使用SynchronousQueue作为工作队列的前提下,客户端代码向线程池提交任务时,
而线程池中又没有空闲的线程能够从SynchronousQueue队列实例中取一个任务,
那么相应的offer方法调用就会失败(即任务没有被存入工作队列)。
此时,ThreadPoolExecutor会新建一个新的工作者线程用于对这个入队列失败的任务进行处理(假设此时线程池的大小还未达到其最大线程池大小maximumPoolSize)。
// 和Executors.newCachedThreadPool()一样的
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
new SynchronousQueue());
终止线程:
threadPoolExecutor.shutdown();
通过该方式终止线程池后,已经添加到线程池中的任务会执行完,不能在加入新的任务。
List
通过该方式终止的线程池后,线程池中的正在执行的线程将interrupted,而未被执行任务将被返回回来。