java线程池深入一

来源:互联网 发布:js时间计算 编辑:程序博客网 时间:2024/06/05 20:01
一.目的
多线程并行,提升效率,线程重用,减少创建线程开销。

二.基础知识
线程池几个核心要素:
1.核心线程数
当有新的任务进来时,若没有超过这个核心线程数,则会创建新的线程来执行任务。
2.最大线程数
用于限制最多可创建的线程,若超过这个值,默认的策略的抛异常。

3.线程超时时间
当已有线程数超过核心线程数时,超过这个时间,多于核心线程数的线程会被回收释放。

4.队列
用于存储任务。

三.基础流程
假设,当前核心线程数为2,最大线程数是4,线程超时时间是1分钟,队列使用LinkedBlockingQueue大小为10000。
拒绝策略是使任务提交者阻塞。

当任务提交者提交任务时,流程如下:



二.如何使用
一般有以下几种用法:
1.通过Executos工具类创建线程池
固定线程数的线程池ExecutorService executorService=Executors.newFixedThreadPool(10);executorService.submit(new Runnable() {public void run() {System.out.println("hi");}});//缓存线程的线程池ExecutorService cacheExecutorService = Executors.newCachedThreadPool();cacheExecutorService.execute(new Runnable() {public void run() {System.out.println("cached");}});


考虑下这两种线程池有什么问题?

2.直接通过new ThreadPoolExecutor
项目使用中,我们更多的是直接用ThreadPoolExecutor进行个性化定制。
一般我们会设置核心线程数,最大线程数,任务队列最大数,有些时候如果是后台任务则设置允许核心线程也能被回收。
代码如下:
ExecutorService threadPoolExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(1), new WaitRejctHandler());threadPoolExecutor.allowCoreThreadTimeOut(true);threadPoolExecutor.execute(new Runnable() {public void run() {System.out.println("threadPoolExecutor1");}});static class WaitRejctHandler implements RejectedExecutionHandler {public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {try {executor.getQueue().put(r);} catch (InterruptedException e) {e.printStackTrace();}}}

三.存在哪些坑
在第二点如何使用上,Executors提供了方便创建FixedThreadPool及CachedThreadPool两种线程池。
这两种线程在生产者提交任务数过快时,FixedThreadPool会OOM,CachedThreadPool会导致线程数不断增加最终也会导致OOM。
FixedThreadPool底层,核心线程数等于最大线程数(具体线程多少是入参决定),用的是无界LinkedBlockingQueue。
CachedThreadPool底层,核心线程数是0,最大线程数是Integer的MaxValue相当于无限多。而队列使用的SyncronusQueue。
在CachedThreadPool应用场景,SyncronusQueue内部不会存储任何任务。