线程池

作者: YDDMAX_Y | 来源:发表于2019-07-02 10:25 被阅读0次

    线程池执行过程

    1. 如果当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务;
    2. 如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(一般来说是任务缓存队列已满),则会尝试创建新的线程去执行这个任务;
    3. 如果当前线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理;
    4. 如果线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程设置存活时间(allowCoreThreadTimeOut(boolean)),那么核心池中的线程空闲时间超过keepAliveTime,线程也会被终止。
    5. 各个worker取任务的同步过程、keepalive的生效 是通过blockingqueue的功能完成的。


      image.png
    6. 如果调用了shutdown()方法,则线程池处于SHUTDOWN状态,此时线程池不能够接受新的任务,它会等待所有任务执行完毕;
      如果调用了shutdownNow()方法,则线程池处于STOP状态,此时线程池不能接受新的任务,并且会去尝试终止正在执行的任务,而且会丢弃在队列中的任务。

    RejectHandler

    ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
    ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
    ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
    ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

    ThreadPoolExecutor提供了动态调整线程池容量大小的方法

    setCorePoolSize()
    setMaximumPoolSize()

    Executors

    newFixedThreadPool创建的线程池corePoolSize和maximumPoolSize值是相等的,它使用的LinkedBlockingQueue;
    newSingleThreadExecutor将corePoolSize和maximumPoolSize都设置为1,也使用的LinkedBlockingQueue;
    newCachedThreadPool将corePoolSize设置为0,将maximumPoolSize设置为Integer.MAX_VALUE,使用的SynchronousQueue,也就是说来了任务就创建线程运行,当线程空闲超过60秒,就销毁线程。

    ScheduledExecutorService

    对于的实现ScheduledThreadPoolExecutor,线程数永远小于coreSize,不能传入Blockingqueue,内置的queue是无限大小的,线程取任务的同步逻辑依然是依赖的BloingQueue。
    几个参数:
    coreSize:自己设
    maxSize:Integer.MAX_VALUE,实际上该参数不生效
    BlockingQueue:内部实现的DelayedWorkQueue(基于极小堆,实际上功能和DelayQueue是相同的,compareTo比较的是要执行的时间,getDelay返回的是还要多久执行。),没有设置上限size
    具体实现:
    execute和submit最后调的都是schedule(delay时间为0),schedule时的逻辑如下。所以:对于ScheduleExecutorService其运行的线程数永远小于等于coreSize,不会超过coreSize。每次schedule(execute和submit也是)都是先向queue添加task,然后执行ensurePrestart,不会判断maxSize

    private void delayedExecute(RunnableScheduledFuture<?> task) {
            if (isShutdown())
                reject(task);
            else {
                super.getQueue().add(task);
                if (isShutdown() &&
                    !canRunInCurrentRunState(task.isPeriodic()) &&
                    remove(task))
                    task.cancel(false);
                else
                    ensurePrestart();
            }
        }
    
     void ensurePrestart() {
            int wc = workerCountOf(ctl.get());
            if (wc < corePoolSize)
                addWorker(null, true);
            else if (wc == 0)
                addWorker(null, false);
        }
    

    参考:线程池

    相关文章

      网友评论

        本文标题:线程池

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