zoukankan      html  css  js  c++  java
  • 并发包的线程池第二篇--Executors的构造

    上一篇讲述了ThreadPoolExecutor的执行过程,我们也能看出来一个很明显的问题:这个线程池的构造函数比较复杂,对于不十分理解其运作原理的程序员,自己构造它可能体现和想象中不一样的行为。比如阻塞队列放什么,corePoolSize怎么设置等等。

    所以和Math这种工具类一样,并发包也提供了一种工具类:Executors。

    首先这个工具类的作用就是:提供静态方法帮你构造不同的线程池。那么先分析一下它的设计模式:

    1,静态工厂方法模式,静态方法帮你构造线程池。

    2,外观模式,用一个简单的接口屏蔽了内部细节。(这么说有一点点牵强)

    这个Executors提供的最主要的工厂有三种:

     1     public static ExecutorService newFixedThreadPool(int nThreads) {
     2         return new ThreadPoolExecutor(nThreads, nThreads,
     3                                       0L, TimeUnit.MILLISECONDS,
     4                                       new LinkedBlockingQueue<Runnable>());
     5     }
     6 
     7     public static ExecutorService newSingleThreadExecutor() {
     8         return new FinalizableDelegatedExecutorService
     9             (new ThreadPoolExecutor(1, 1,
    10                                     0L, TimeUnit.MILLISECONDS,
    11                                     new LinkedBlockingQueue<Runnable>()));
    12     }
    13 
    14     public static ExecutorService newCachedThreadPool() {
    15         return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
    16                                       60L, TimeUnit.SECONDS,
    17                                       new SynchronousQueue<Runnable>());
    18     }

    第一种:大小固定的线程池,构造的时候必须告知其最大线程数量(无论如何也不超过这个数字),同时corePoolSize和maximumPoolSize都直接设置为这个最大线程数目参数。keepAliveTime则设置为0。(根本没有“短工”,也就谈不上短工的存活时间了)

    重要的来了:为什么阻塞队列是一个无界队列(其实也不完全是无界:Integer.MaxValue)?这其实是设计很有意思的一个地方。我们之前已经说过线程池的运行逻辑。如果把阻塞队列设置为无限大,那么在实际线程数量达到corePoolSize之后,再来的线程都会阻塞在这个队列里面。从而保证:根本就没有“短工”。也就限制了线程池的总大小。

    第二种:只持有一个线程的线程池,直接把corePoolSize和maximumPoolSize都设置为1,没啥说的

    第三种:线程池是无界的。而阻塞队列是一个SynchronousQueue,这个队列的特点是不存放对象的阻塞队列。每一次take必须先于put,换句话说和别的先放再取的队列不一样,这个队列是先“预订”,等一“到货”,立马“交付”。每一个操作都是先做:然后立马阻塞,等别人对应的操作来取,实现几乎直接的交付。

    逻辑变成了:因为核心池大小为0,没有长工。放进来的线程先试图进入SynchronousQueue,如果在此之前有worker做完了自己的工作,去SynchronousQueue拿线程(然后被阻塞),就可以实现直接交付给这个空闲的worker执行。如果失败(没有worker是空闲的),那么因为进入失败会直接新建一个worker,进入maximumPool开始执行。而那些执行完自己task都去SynchronousQueue等60秒,如果还有“订单”要来,就开工干活,否者keepAliveTime到被销毁。

  • 相关阅读:
    网络杂项
    虚拟化
    虚拟化
    ssh
    开机启动命令/服务
    选择表达式
    查询一个表中的重复数据
    oracle逗号分隔函数
    只能为浮点数或整数的正则表达式
    后台模拟弹出上传匡
  • 原文地址:https://www.cnblogs.com/dsj2016/p/5844362.html
Copyright © 2011-2022 走看看