Java并发编程日记——线程池介绍和使用建议

JDK中有四种线程池,分别是FixedThreadPoolSingleThreadExecutorCachedThreadPoolScheduledThreadPool,他们都依赖一个核心类ThreadPoolExecutor

ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}
  • corePoolSize:池中线程的数量保持,即使这些应用程序处于空闲状态,除非核心线程时间被设置
  • maximumPoolSize:线程池中允许的最大数量
  • keepAliveTime:当线程的数量大于核心线程数,空闲线程终止之前将等待新的任务的最长时间,一旦超过这个时间,空闲的线程将被回收,直至线程数等于核心线程数
  • unit:keepAliveTime的时间单位
  • workQueue:队列用于执行任务之前。这个队列只持有excute方法提交的Runnable任务

FixedThreadPool

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

FixedThreadPool是固定线程数的线程池,核心线程等于最大线程数,超过核心线程数空闲的线程马上被回收。任务队列使用的是LinkedBlockingQueue,LinkedBlockingQueue的大小是Integer.MAX_VALUE。

SingleThreadExecutor

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

SingleThreadExecutor是单一线程数的线程池,核心线程和最大线程数等于1,超过核心线程数空闲的线程马上被回收。任务队列使用的是LinkedBlockingQueue,LinkedBlockingQueue的大小是Integer.MAX_VALUE。

CachedThreadPool

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

CachedThreadPool是缓存线程数的线程池,核心线程为0,最大线程数为Integer.MAX_VALUE,超过核心线程数空闲的线程超过60秒会被回收。任务队列使用的是SynchronousQueue,SynchronousQueue作为主线程池的工作队列,它是一个没有容量的阻塞队列。每个插入操作必须等待另一个线程的对应移除操作。这意味着,如果主线程提交任务的速度高于线程池中处理任务的速度时,CachedThreadPool会不断创建新线程。

ScheduledThreadPool

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
}

ScheduledThreadPool是执行定时任务的线程池,核心线程为传入值,最大线程数等于Integer.MAX_VALUE,超过核心线程数空闲的线程马上被回收。任务队列使用的是DelayedWorkQueue,DelayedWorkQueue实现了LinkedBlockingQueue的接口,大小是Integer.MAX_VALUE。

在日常的开发中,不建议直接使用Executors直接去创建以上这些线程池,而是自己通过显式的ScheduledThreadPoolExecutor去创建
Executors各个方法的弊端:
1.newFixedThreadPoolnewSingleThreadPool
主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
2.newCachedThreadPoolnewScheduledThreadPool
主要问题是线程数最大数是Integer.MAX_VALUE,可能会常见数量非常多的线程,甚至OOM

建议使用创建的方法是

    ExecutorService pool = new ThreadPoolExecutor(5,200,
            0L,TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1024),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());

当任务超过队列的大小时,需要执行一些拒绝的策略

  • CallerRunsPolicy:只要当前线程没有被关闭就继续执行
  • AbortPolicy:直接抛出RejectedExecutionException异常带有线程信息
  • DiscardPolicy:直接扔掉这个任务
  • DiscardOldestPolicy:扔掉最老的,执行新加入的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值