线程池
之前在使用线程的时候,不管是继承Thread类还是实现Runnable或者Callable接口,都需要使用new Thread来创建线程,用完之后直接销毁,频繁的创建销毁线程比较浪费资源,于是出现了线程池的概念。
线程池中提供了一个线程队列,队列中保存着所有等待状态的线程,避免了创建和销毁的额外开销,提高了响应速度

Executors
在一般情况下使用线程池都是直接使用Executors类中提供的静态方法来直接创建线程池,这是jdk提供创建线程池的工具类,但是要用好这个工具类,一定要清楚每个方法所生成的线程池的特性以及线程池中每个参数的含义。
几种常用的创建线程池的方法
newFixedThreadPool
创建固定大小的线程池
1 | public static ExecutorService newFixedThreadPool(int nThreads) { |
newSingleThreadExecutor
创建单个线程的线程池
1 | public static ExecutorService newSingleThreadExecutor() { |
newCachedThreadPool
缓存线程池,可以根须需求自动的更改数量
1 | public static ExecutorService newCachedThreadPool() { |
newSingleThreadScheduledExecutor
创建固定大小的线程池,可以延迟或定时的执行任务
1 | public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { |
newWorkStealingPool (工作窃取线程池)
大型的任务被分解成若干块放入到队列中,在队列中还可以继续细分,线程从队列中获取任务并进行执行,当所有的线程计算结束之后,再将各部分的结果进行合并来得到最终结果。
在处理器之间分配工作项,从而最大限度的利用所有可用的处理器来完成计算密集型任务,这项算法也用于 Java 的fork/join 框架
1 | ExecutorService executorService = Executors.newWorkStealingPool(); |
线程池的提交和关闭
ExecutorService接口中提供了提交任务和关闭线程池的方法
1 | //提交 为线程池中的线程分配任务 |
1 | // 优雅的停止,等线程池任务执行完毕停止 |
submit()方法和execute()方法都可以提交任务执行,这两者有什么不同呢
- submit()方法有返回值Future,而execute()方法是没有返回值的
但是对于ScheduledExecutorService延时调度,使用以下方法
1 | public ScheduledFuture<?> schedule(Runnable command, |
ForkJoinPool(分支合并)
存在一个大任务,将大任务进行拆分(fork)成若干个小任务,再将一个个的小任务运算进行join操作
底层采用了工作窃取模式