自定义线程池,如何最佳创建线程池

java有预置线程池:newSingleThreadExecutor,newFixedThreadPool,newCacheedThreadPool,newScheduledThreadPool,newWorkStealingPool。如果不适合,还可以使用ThreadPoolExecutor创建自定义线程池。主要构造方法:

 1 public ThreadPoolExecutor(int corePoolSize,
 2                           int maximumPoolSize,
 3                           long keepAliveTime,
 4                           TimeUnit unit,
 5                           BlockingQueue<Runnable> workQueue)
 6 
 7 public ThreadPoolExecutor(int corePoolSize,
 8                           int maximumPoolSize,
 9                           long keepAliveTime,
10                           TimeUnit unit,
11                           BlockingQueue<Runnable> workQueue,
12                           ThreadFactory threadFactory,
13                           RejectedExecutionHandler handler)

我们接下来介绍参数,其中线程池大小与前四个参数有关。

  • corePoolSize: 核心线程数。
    • 刚创建线程池,没有,即不会预先创建。当任务到来,且当前线程没有超过corePoolSize,就会创建一个新线程执行该任务,即使其他线程是空闲。
    • 不会因为空闲而被释放,keepAliveTime不适用。
  • maximumPoolSize:最大线程数。如上面情况,如果当前线程超过corePoolSize,先尝试排队,如果队列满了或者其他情况不能入队,那么它不会排队,而是检查线程数是否达到maximumPoolSize,如果没有,就创建线程,直到线程数达到maximumPoolSize。
  • keepAliveTime:空闲线程存活时间。当线程池的线程数大于corePoolSize,额外空闲线程的存活时间。如果到了时间,还没有新任务,就会释放线程。值为0,表示线程不会超时释放。
  • unit
  • BlockingQueue:阻塞队列。可以使用LinkedBlockingQueue(默认无界)、ArrayBlockingQueue、PriorityBlockingQueue(无界)、SynchronousQueue(没实际存储空间)。使用无界队列,需要注意,线程数最多达到corePoolSize,新任务来只能排队,maximumPoolSize没意义。SynchronousQueue只有正好有空闲线程,才会入队成功,否则总是创建新线程,直到达到maximumPoolSize。
  • handler:任务拒绝策略。有界队列,线程数达到maximumPoolSize,队列满了,触发任务拒绝策略。四种处理方式:AbortPolicy(默认,抛出异常),DiscardPolicy(忽略新任务,不抛异常),DiscardOldestPolicy(扔掉等待时间最长,自己排队),CallerRunsPolicy(任务提交者线程执行任务)

最佳自定义创建线程池,队列有界,maximumPoolSize有限,使用任务拒绝策略。如果队列无界,服务不了的任务总是会排队,消耗内存,甚至引发内存不足异常。如果队列有界但maximumPoolSize无线,可能会创建过多线程,占内存和CPU。

猜你喜欢

转载自www.cnblogs.com/ivy-xu/p/12607811.html