美文网首页
线程池解析

线程池解析

作者: 迷糊小生 | 来源:发表于2019-04-06 14:29 被阅读0次

    参考文章:https://www.cnblogs.com/dongguacai/p/6030187.html
    https://www.cnblogs.com/easycloud/p/3726089.html

    线程池的构造方法

     public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue) {
            this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 Executors.defaultThreadFactory(), defaultHandler);
        }
    
    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory) {
            this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 threadFactory, defaultHandler);
        }
    
     public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  RejectedExecutionHandler handler) {
            this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 Executors.defaultThreadFactory(), handler);
        }
    
        /**
         * @param corePoolSize 线程池核心线程数量
         * @param maximumPoolSize 线程池最大线程数量
         * @param keepAliveTime 当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间
         * @param unit 存活时间的单位
         * @param workQueue 存放任务的队列
         * @param threadFactory 线程工厂
         * @param handler 超出线程范围和队列容量的任务的处理程序
         */
    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory,
                                  RejectedExecutionHandler handler) {
            if (corePoolSize < 0 ||
                maximumPoolSize <= 0 ||
                maximumPoolSize < corePoolSize ||
                keepAliveTime < 0)
                throw new IllegalArgumentException();
            if (workQueue == null || threadFactory == null || handler == null)
                throw new NullPointerException();
            this.acc = System.getSecurityManager() == null ? null:AccessController.getContext();
            this.corePoolSize = corePoolSize;
            this.maximumPoolSize = maximumPoolSize;
            this.workQueue = workQueue;
            this.keepAliveTime = unit.toNanos(keepAliveTime);
            this.threadFactory = threadFactory;
            this.handler = handler;
        }
    

    从以上线程池的构造方法里不难看出,其所有的构造方法实际上都是调用的最后一个构造方法,只是线程工厂和任务处理器的不同而已。

    workQueue:存放任务的队列
    (1)ArrayBlockingQueue,有界队列。是一种基于数组的有界阻塞队列;
    (2)LinkedBlockingQueue,无界队列。是一个基于链表的阻塞队列,吞吐量通常要高于ArrayBlockingQueue, Executors.newFixedThreadPool()使用了这种队列;
    (3)SynchronousQueue;直接提交。是一种不存储元素的阻塞队列,每个插入操作必须等另一个线程调用移除操作,否则插入操作一直处于阻塞状态。Executors.newCachedThreadPool使用了这个队列;
    (4)PriorityBlockingQueue,是一种具有优先权的阻塞队列,优先级大的任务可以先执行,用户由此可以控制任务的执行顺序。
    threadFactory:创建新线程时使用的工厂
    (1)Executors.DefaultThreadFactory,将创建一个同线程组且默认优先级的线程;
    (2)Executors.PrivilegedThreadFactory,使用访问权限创建一个权限控制的线程。ThreadPoolExecutor默认采用DefaultThreadFactory
    handler(饱和策略):超出线程范围和队列容量的任务的处理程序
    (1)ThreadPoolExecutor.AbortPolicy(),将抛出RejectedExecutionException异常;
    (2)ThreadPoolExecutor.CallerRunsPolicy(),将重试添加当前的任务,重复调用execute()方法;
    (3)ThreadPoolExecutor.DiscardOldestPolicy(),将抛弃旧任务;
    (4)ThreadPoolExecutor.DiscardPolicy,将直接抛弃任务。ThreadPoolExecutor默认采用AbortPolicy。

    线程池原理

    一个任务通过execute(Runnable)方法被添加到线程池,任务必须是一个 Runnable类型的对象,任务的执行方法就是调用Runnable类型对象的run()方法。当一个任务通过execute(Runnable)方法欲添加到线程池时,会做一下几步:

    1. 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。

    2. 如果此时线程池中的数量大于等于corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。

    3. 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理添加的任务。

    4. 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。

    5. 当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

    image.png

    Executors可以创建3种类型线程池

    (1)SingleThreadExecutor:单线程线程池

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

    (2)FixedThreadExecutor:固定大小线程池

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

    (3)CachedThreadPool:无界线程池

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

    相关文章

      网友评论

          本文标题:线程池解析

          本文链接:https://www.haomeiwen.com/subject/egbliqtx.html