资讯专栏INFORMATION COLUMN

线程池的状态及KeepAliveTime参数

Yang_River / 1825人阅读

摘要:在程序某些必要的情况下,可以通过线程池的,,,来对线程做一些状态判定。默认的工厂,只有,为秒,出现情况下,而且线程数超过了核心线程数,会销毁销毁线程。线程池最小是,最大是,除非设置了和超时时间,这种情况线程数可能减少到,最大可能是。

五个状态
    // runState is stored in the high-order bits
    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;
循环getTask方法
/**
     * Performs blocking or timed wait for a task, depending on
     * current configuration settings, or returns null if this worker
     * must exit because of any of:
     * 1. There are more than maximumPoolSize workers (due to
     *    a call to setMaximumPoolSize).
     * 2. The pool is stopped.
     * 3. The pool is shutdown and the queue is empty.
     * 4. This worker timed out waiting for a task, and timed-out
     *    workers are subject to termination (that is,
     *    {@code allowCoreThreadTimeOut || workerCount > corePoolSize})
     *    both before and after the timed wait.
     *
     * @return task, or null if the worker must exit, in which case
     *         workerCount is decremented
     */
    private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);
            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }
            boolean timed;      // Are workers subject to culling?
            for (;;) {
                int wc = workerCountOf(c);
                timed = allowCoreThreadTimeOut || wc > corePoolSize;
                //默认allowCoreThreadTimeOut为false,除非程序指定
                //(1)当没有超过核心线程时,默认allowCoreThreadTimeOut为false时
                //timed值为false,始终break掉,不会销毁线程
                //(2)当超过核心线程数,默认allowCoreThreadTimeOut为false时
                //timed值为true,如果超过最大值,则销毁;如果timeout过,则销毁
                // 如果allowCoreThreadTimeOut为true,则timed始终为true
                if (wc <= maximumPoolSize && ! (timedOut && timed))
                    break;
                if (compareAndDecrementWorkerCount(c))
                    return null;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
            try {
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }
线程池状态大于SHUTDOWN值的两种情况 1、调用shutdown方法

当线程池调用了shutdown方法,线程池的状态会首先被设置为SHUTDOWN,然后遍历线程池中所有线程,调用一次interrupt方法,如果在休眠中的线程将会激活,激活后的线程以及调用shutdown方法本身的线程都会尝试去调用tryTerminate方法,该方法将判定如果线程池中所有记录的线程数为0,则将线程状态改为TERMINATED,这个值为3,将大于SHUTDOWN状态值。

2、调用shutdownNow方法

当线程调用了shutdownNow方法后,首先将线程的状态修改为STOP,这个状态是大于SHUTDOWN值的,接下来它也会通过中断激活线程,只是它来的更暴力一些,连加锁和一些基本判断都没有,直接中断;在调用tryTerminate之前会先清空阻塞队列中所有的元素,这些元素被组装为一个List列表作为shutdownNow方法的返回值。换句话说,没有执行的任务在shutdownNow执行后的返回值中可以得到。在程序某些必要的情况下,可以通过线程池的isTerminating,isTerminated,isStopped,isShutdown来对线程做一些状态判定。

KeepAliveTime参数
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)

当阻塞队列中没有任务时,等待时间达到keepAliveTime毫秒值时就会被自动唤醒,而不会永远地沉睡下去。

keepAliveTime,如果是通过newCachedThreadPool的话,默认是1分钟超时,如果遇到前面所提到的瞬间冲击,那么线程池数量将瞬间快速膨胀,而且这些瞬间膨胀的线程的生命周期最少在1分钟以上。

如果设置了该参数,那么当timeout的时候,就return null,就会跳出循环,回收线程。

if (wc <= maximumPoolSize && ! (timedOut && timed))
                    break;
                if (compareAndDecrementWorkerCount(c))
                    return null;

allowCoreThreadTimeout : 默认情况下核心线程不会退出,可通过将该参数设置为true,让核心线程也退出。

默认的Executors工厂,只有newCachedThreadPool,timeout为60秒,出现timeout情况下,而且线程数超过了核心线程数,会销毁销毁线程。保持在corePoolSize数(如果是cached的,corePoolSize为0)。

   /**
     * Timeout in nanoseconds for idle threads waiting for work.
     * Threads use this timeout when there are more than corePoolSize
     * present or if allowCoreThreadTimeOut. Otherwise they wait
     * forever for new work.
     */
    private volatile long keepAliveTime;
    /**
     * If false (default), core threads stay alive even when idle.
     * If true, core threads use keepAliveTime to time out waiting
     * for work.
     */
    private volatile boolean allowCoreThreadTimeOut;

线程池最小是corePoolSize,最大是maximumPoolSize,除非设置了allowCoreThreadTimeOut和超时时间,这种情况线程数可能减少到0,最大可能是Integer.MAX_VALUE。

Core pool size is the minimum number of workers to keep alive(and not allow to time out etc) unless allowCoreThreadTimeOut is set, in which case the minimum is zero.

/**
     * Creates a thread pool that creates new threads as needed, but
     * will reuse previously constructed threads when they are
     * available.  These pools will typically improve the performance
     * of programs that execute many short-lived asynchronous tasks.
     * Calls to execute will reuse previously constructed
     * threads if available. If no existing thread is available, a new
     * thread will be created and added to the pool. Threads that have
     * not been used for sixty seconds are terminated and removed from
     * the cache. Thus, a pool that remains idle for long enough will
     * not consume any resources. Note that pools with similar
     * properties but different details (for example, timeout parameters)
     * may be created using {@link ThreadPoolExecutor} constructors.
     *
     * @return the newly created thread pool
     */
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue());
    }
    /**
     * Creates a thread pool that creates new threads as needed, but
     * will reuse previously constructed threads when they are
     * available, and uses the provided
     * ThreadFactory to create new threads when needed.
     * @param threadFactory the factory to use when creating new threads
     * @return the newly created thread pool
     * @throws NullPointerException if threadFactory is null
     */
    public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue(),
                                      threadFactory);
    }
超时timeout设置为0的话,表示不等待
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
        return pollFirst(timeout, unit);
    }

具体如下

public E pollFirst(long timeout, TimeUnit unit)
        throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            E x;
            while ( (x = unlinkFirst()) == null) {
                if (nanos <= 0)
                    return null;
                nanos = notEmpty.awaitNanos(nanos);
            }
            return x;
        } finally {
            lock.unlock();
        }
    }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65818.html

相关文章

  • Android 线程池的类型、区别以为何要用线程

    摘要:线程池根据当前在系统中运行的进程来优化线程片。线程池可以用来解决处理一个特定请求最大线程数量限制问题。线程池中允许的线程最大数量,当活动线程达到这个数值后,后续的新任务会被阻塞。 每个 Android 应用进程在创建时,会同时创建一个线程,我们称之为主线程,负责更新 UI 界面以及和处理用户之间的交互,因此,在 Android 中,我们又称之为 UI 线程。一个进程中 UI 线程只有一...

    caiyongji 评论0 收藏0
  • java并发编程学习2--Future

    摘要:一个线程池包含很多准备运行的空闲线程,每当执行完毕后,线程不会死亡而是回到线程池准备为下一个请求提供服务。另一个使用线程池的理由是减少并发线程数。创建大量线程会大大降低性能甚至拖垮虚拟机。 【Future的概念 interface Future ,表示异步计算的结果,Future有个get方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,然后会返回结果或者抛出异常...

    weizx 评论0 收藏0
  • 后端ing

    摘要:当活动线程核心线程非核心线程达到这个数值后,后续任务将会根据来进行拒绝策略处理。线程池工作原则当线程池中线程数量小于则创建线程,并处理请求。当线程池中的数量等于最大线程数时默默丢弃不能执行的新加任务,不报任何异常。 spring-cache使用记录 spring-cache的使用记录,坑点记录以及采用的解决方案 深入分析 java 线程池的实现原理 在这篇文章中,作者有条不紊的将 ja...

    roadtogeek 评论0 收藏0
  • 线程池源码分析

    摘要:线程池的作用线程池能有效的处理多个线程的并发问题,避免大量的线程因为互相强占系统资源导致阻塞现象,能够有效的降低频繁创建和销毁线程对性能所带来的开销。固定的线程数由系统资源设置。线程池的排队策略与有关。线程池的状态值分别是。 线程池的作用 线程池能有效的处理多个线程的并发问题,避免大量的线程因为互相强占系统资源导致阻塞现象,能够有效的降低频繁创建和销毁线程对性能所带来的开销。 线程池的...

    enda 评论0 收藏0

发表评论

0条评论

Yang_River

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<