线程池的四种创建方式及应用场景(注意仅供demo演示,实际推荐手动创建线程池的方式)

关于三种线程池的三种队列区别:SynchronousQueue、LinkedBlockingQueue 和ArrayBlockingQueue,可以点击链接查看。

最近线程池用的比较多,感觉挺有意思。在此记录一下,线程池的创建有4种方式;
1 .Executors.newCachedThreadPool();
构造方法为:

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


官方的注释中注明,该线程池适用于短时间的异步任务较多的场景。这类线程池的特点就是里面没有核心线程全是非核心线程,其maximumPoolSize设置为Integer.MAX_VALUE,线程可以无限创建,当线程池中的线程都处于活动状态的时候,线程池会创建新的线程来处理新任务,否则会用空闲的线程来处理新任务,这类线程池的空闲线程都是有超时机制的,keepAliveTime在这里是有效的,时长为60秒,超过60秒的空闲线程就会被回收,当线程池都处于闲置状态时,线程池中的线程都会因为超时而被回收,所以几乎不会占用什么系统资源。任务队列采用的是同步队列SynchronousQueue,该队列不会缓冲元素,有消费时,才会继续添加任务到队列中,也就是一有任务立即执行,所以CachedThreadPool比较适合任务量大但耗时少的任务


2 .Executors.newFixedThreadPool(3);

构造方法为:

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

这类线程池的特点,是一个固定数量的线程池,就是里面全是核心线程,没有非核心线程,也没有超时机制,任务大小也是没有限制的,数量固定,即使是空闲状态,线程不会被回收,除非线程池被关闭,从构造方法也可以看出来,只有两个参数,一个是指定的核心线程数,一个是线程工厂,keepAliveTime无效。任务队列采用了无界的阻塞队列LinkedBlockingQueue,执行execute方法的时候,运行的线程没有达到corePoolSize就创建核心线程执行任务,当任务数量超过我们设定的线程数时,线程池会将任务投递到无界队列中,阻塞在任务队列中,这个时候一定要控制投递任务的数量。有空闲线程的时候去取任务执行。由于该线程池线程数固定,且不被回收,线程与线程池的生命周期同步,所以适用于任务量比较固定但耗时长的任务。


3 .Executors.newScheduledThreadPool(10);

构造方法为:

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
   return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
   super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());
}
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
   this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
}

这类线程池核心线程数量是固定的,好像和FixThreadPool有点像,但是它的非核心线程是没有限制的,并且非核心线程一闲置就会被回收,keepAliveTime同样无效,意思是:只要线程工作完,立马就会被回收,不会有空闲时间。因为核心线程是不会回收的,当运行的线程数没有达到corePoolSize的时候,就新建线程去DelayedWorkQueue中取ScheduledFutureTask然后才去执行任务,否则就把任务添加到DelayedWorkQueue,DelayedWorkQueue会将任务排序,按新建一个非核心线程顺序执行,执行完线程就回收,然后循环。任务队列采用的DelayedWorkQueue是个无界的队列,延时执行队列任务,或者每隔一段时间执行一个任务。综合来说,这类线程池适用于执行定时任务和具体固定周期的重复任务。


4 .Executors.newSingleThreadExecutor();

构造方法为:

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

这类线程池顾名思义就是创建一个单线程的连接池,细心的朋友会想,这种构造方式和new FixedThreadPool(1)有什么区别呢? 根据官方注释上说,两者的区别是:后者可以重新构造核心线程的数量,但是前者不行。意思就是FixedThreadPool构造完成后可以设置核心线程的数量,但是singleThreadExecutor不行。SingleThreadExecutor不能重新构造核心线程的原因:根据源码看,是因为被FinalizableDelegatedExecutorService包了一层。不能强转成ThreadPoolExecutor,所以不能重新设置核心线程。其任务队列是LinkedBlockingQueue,这是个无界的阻塞队列,因为线程池里只有一个线程,就确保所有的任务都在同一个线程中顺序执行,这样就不需要处理线程同步的问题。这类线程池适用于多个任务顺序(FIFO执行的场景

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值