当前位置: 首页 > 编程笔记 >

java 线程池keepAliveTime的含义说明

贺方伟
2023-03-14
本文向大家介绍java 线程池keepAliveTime的含义说明,包括了java 线程池keepAliveTime的含义说明的使用技巧和注意事项,需要的朋友参考一下

之前对线程池中属性:keepAliveTime比较模糊,而且看过之后过一段时间就会忘掉,于是就在此记录一下。

keepAliveTime的jdk中的解释为:

当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。

说的让人感觉比较模糊,总结一下大概意思为:比如说线程池中最大的线程数为50,而其中只有40个线程任务在跑,相当于有10个空闲线程,这10个空闲线程不能让他一直在开着,因为线程的存在也会特别好资源的,所有就需要设置一个这个空闲线程的存活时间,这么解释应该就很清楚了。

这样以后忘记了就过来看看就OK了。

补充:线程池的状态及KeepAliveTime参数

五个状态

 // 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,让核心线程也退出。

默认的Executorshtml" target="_blank">工厂,只有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 <tt>execute</tt> 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<Runnable>());
 }
 /**
  * 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<Runnable>(),
          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();
  }
 }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持小牛知识库。如有错误或未考虑完全的地方,望不吝赐教。

 类似资料:
  • 主要内容:1 什么是Java 线程池,2 Java 线程池的优势,3 Java 线程池的应用场景,4 Java 线程池的例子1 什么是Java 线程池 Java线程池 表示一组正在等待作业并多次重复使用的工作线程。 如果是线程池,则会创建一组固定大小的线程。服务提供商从线程池中拉出一个线程并为其分配作业。作业完成后,线程再次包含在线程池中。 2 Java 线程池的优势 由于无需创建新线程,因此拥有更好的性能,可以节省时间。 3 Java 线程池的应用场景 在用户请求Servlet和JSP时,其中

  • SOFARPC 支持自定义业务线程池。可以为指定服务设置一个独立的业务线程池,和 SOFARPC 自身的业务线程池是隔离的。多个服务可以共用一个独立的线程池。 SOFARPC 要求自定义线程池的类型必须是 com.alipay.sofa.rpc.server.UserThreadPool。 XML 方式 如果采用 XML 的方式发布服务,可以先设定一个 class 为 com.alipay.sof

  • 出于学习的目的,我正在尝试用java实现自己的线程池。下面是我已经实现的。我对这个实现有几个问题: > 虽然我像内置java一样使用BlockingQueue执行器希望我们提供Runnable对象(通过执行方法)。但在我的情况下,我觉得我可以创建任何对象而不是Runnable。那么为什么Java执行器期望Runnable,我尝试查看源代码,但还不能弄清楚。 这个原始实现还有什么问题吗? 请找到密码

  • 一、概述 在我们的开发中经常会使用到多线程。例如在Android中,由于主线程的诸多限制,像网络请求等一些耗时的操作我们必须在子线程中运行。我们往往会通过new Thread来开启一个子线程,待子线程操作完成以后通过Handler切换到主线程中运行。这么以来我们无法管理我们所创建的子线程,并且无限制的创建子线程,它们相互之间竞争,很有可能由于占用过多资源而导致死机或者OOM。所以在Java中为我们

  • 每个人我对使用线程池有一个误解。实际结果与该类的API描述不同。当我在线程池中使用时,它不重用线程,线程池等待构造函数中设置的KeepAliveTime,然后杀死这个线程并创建一个新线程。当我将KeepAliveTime设置为较小值时,比如1秒或更短,它会删除一个线程并重新创建它,但如果我设置一分钟,则不会创建新线程,因为不允许创建,队列已经满,所以所有任务都会被拒绝,但KeepAliveTime

  • 由来 在JDK中,提供了Executors用于创建自定义的线程池对象ExecutorService,但是考虑到线程池中存在众多概念,这些概念通过不同的搭配实现灵活的线程管理策略,单独使用Executors无法满足需求,构建了ExecutorBuilder。 概念 corePoolSize 初始池大小 maxPoolSize 最大池大小(允许同时执行的最大线程数) workQueue 队列,用于存在