为什么不能直接自动创建线程池
首先自动创建线程池通过直接调用Executors.newXXXXThreadPool()方法直接创建线程池.但是开发中我们不能直接使用创建的线程池,原因如下:
FixedThreadPool
通过下面FiexdThreadPool内部代码可以看出,FixedThreadPool内部调用的是ThreadPoolExecutor的构造函数,构造函数中是的的阻塞队列是LinkedBlockingQueue,那么这就带来了问题,当任务处理速度比较慢的时候,虽然新增任务越来越多,队列中堆积的任务就越来越多,最终会占用大量内存,并发生OOM,就会严重影响到程序运行.
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()); }
SingleThreadExecutor
通过看下面SingleThreadExecutor的内部代码可以发现,newSingleThreadExecutor和newFixedThreadPool的原理是一样的,只不过是核心线程数和最大线程数都设置成了1,但是任务队列还是无界的LinkedBlockingQueue,所以也会导致任务堆积,发生OOM问题.
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>())); }
CachedThreadPool
继续看下图CachedThreadPool内部代码,从代码中可以看出,CachedThreadPool使用的任务阻塞队列是SynchronousQueue,SynchronousQueue队列我们前面介绍过,并不存储任务,只是对任务进行直接转发,这个队列不会引发OOM问题,但是我们在看最大线程数设置成了Integer.MAX_VALUE,所以CachedThreadPool线程池并不线程的数量,那么任务特别多的时候,就会创建非常多的线程,进而导致系统内存不足.
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>()); }
ScheduledThreadPool和SingleThreadScheduledExector
ScheduledThreadPool和SingleThreadScheduledExector差不多,只不过是后者线程池中只有一个线程,ScheduledThreadPool的源码如下:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
我们在进入ScheduledThreadPoolExecutor构造方法中去,从下图可以看出,它采用的任务队列是DelayWorkQueue,上面我们说过这个队列一个延迟队列同时也是一个无界队列,所以它和LinkedBlockingQueue一样,如果任务过多就可能OOM,代码如下:
public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue()); }
SingleThreadExecutor
第四种线程池中只有一个线程去执行任务,如果执行任务过程中发生了异常,则线程池会创建一个新线程来执行后续任务,这个线程因为只有一个线程,所以可以保证任务执行的有序性.

浙公网安备 33010602011771号