美文网首页
线程池-2种创建方式

线程池-2种创建方式

作者: rock_fish | 来源:发表于2020-08-10 17:23 被阅读0次

    一、通过Executors工厂来创建线程池(慎用)

    Methods that create and return an ExecutorService set up with commonly useful configuration settings.
    Methods that create and return a ScheduledExecutorService set up with commonly useful configuration settings.
    Methods that create and return a "wrapped" ExecutorService, that disables reconfiguration by making implementation-specific methods inaccessible.
    Methods that create and return a ThreadFactory that sets newly created threads to a known state.
    Methods that create and return a Callable out of other closure-like forms, so they can be used in execution methods requiring Callable.
    

    具体的工厂方法如下:

    java.util.concurrent.Executors#newFixedThreadPool(int)
    java.util.concurrent.Executors#newWorkStealingPool(int)
    java.util.concurrent.Executors#newWorkStealingPool()
    java.util.concurrent.Executors#newFixedThreadPool(int, java.util.concurrent.ThreadFactory)
    java.util.concurrent.Executors#newSingleThreadExecutor()
    java.util.concurrent.Executors#newSingleThreadExecutor(java.util.concurrent.ThreadFactory)
    java.util.concurrent.Executors#newCachedThreadPool()
    java.util.concurrent.Executors#newCachedThreadPool(java.util.concurrent.ThreadFactory)
    java.util.concurrent.Executors#newSingleThreadScheduledExecutor()
    java.util.concurrent.Executors#newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory)
    java.util.concurrent.Executors#newScheduledThreadPool(int)
    java.util.concurrent.Executors#newScheduledThreadPool(int, java.util.concurrent.ThreadFactory)
    java.util.concurrent.Executors#unconfigurableExecutorService
    java.util.concurrent.Executors#unconfigurableScheduledExecutorService
    

    大体分为以下4类:

    1、 newSingleThreadExecutor

    创建一个单线程的线程池,保证所有任务按照提交顺序执行
    适用:一个任务一个任务执行的场景

    2、newFixedThreadPool

    创建一个固定大小的线程池,因为采用无界的阻塞队列,所以实际线程数量永远不会变化
    适用:执行长期的任务,性能好很多

    3、newCachedThreadPool

    创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
    适用:执行很多短期异步的小程序或者负载较轻的服务器

    4、 newScheduledThreadPool

    创建一个可定期或者延时执行任务的定长线程池,支持定时及周期性任务执行。
    适用:周期性执行任务的场景

    image.png

    通常不使用这些工厂方法来创建线程池,原因是这些方法所使用的一些参数可能会产生严重的问题,在掌握下边的线程池方法参数的作用的前提下,去评估Executors所提供的方法是否可用。

    二、 手动 new ThreadPollExecutor(xxx)

    显式的通过构造方法来创建线程池。

    image.png
        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;
        }
    
    1、corePoolSize(线程池基本大小):
    • 当向线程池提交一个任务时,若线程池已创建的线程数小于corePoolSize,即便此时存在空闲线程,也会通过创建一个新线程来执行该任务,直到已创建的线程数大于或等于corePoolSize时。
    • 除了利用提交新任务来创建和启动核心线程,也可以通过 prestartCoreThread() 或 prestartAllCoreThreads() 方法来提前启动线程池中的基本线程。
    2、maximumPoolSize(线程池最大大小)
    • 线程池所允许的最大线程个数。
    • 当队列满了,且已创建的线程数小于maximumPoolSize,则线程池会创建新的线程来执行任务。
    • 对于无界队列,可忽略该参数
    3、keepAliveTime、TimeUnit unit(线程存活保持时间)
    • 当线程池中线程数大于核心线程数时,线程的空闲时间如果超过线程存活时间,那么这个线程就会被销毁,直到线程池中的线程数小于等于核心线程数。
    4、workQueue(任务队列)
    • 阻塞队列,用于传输和保存等待执行的任务。
    5、threadFactory(线程工厂)
    • 用于创建新线程。
    • threadFactory创建的线程是用new Thread()的方式
    • 创建的线程名都具有统一的风格:pool-m-thread-n(m为线程池的编号,n为线程池内的线程编号,通俗理解就是几号池的几号线程)。
    • 默认的线程工厂创建的线程是用户线程,优先级为正常优先级。
    6、handler(线程饱和策略)

    当线程池和队列都满了,再来任务会执行此策略。

    线程池任务执行流程:

    1. 当线程池小于corePoolSize时,新提交任务将创建一个新线程来执行任务,即使此时线程池中存在空闲线程。
    2. 当线程池线程数量达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行
    3. 当workQueue已满,且maximumPoolSize>corePoolSize时,对于新提交任务,线程池会创建新的线程来执行
    4. 当线程数超过maximumPoolSize时,且无空闲线程时,新提交任务由RejectedExecutionHandler处理
    5. 当线程池中线程数超过corePoolSize,若线程空闲时间达到keepAliveTime时,将被回收。
    6. 当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

    注意

    • 如果使用无界LinkedBlockingQueue队列的话,因为队列大小没有限制,那么不会拒绝任何任务,ThreadPoolExecutor最多仅会按照最小线程数来创建线程,线程池大小被忽略了。所以要使用定长队列,要设置合理的线程数上线。

    java四种线程池的使用
    Java线程池详解

    相关文章

      网友评论

          本文标题:线程池-2种创建方式

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