JAVA 多线程-newCachedThreadPool()

477 阅读3分钟
  • 常用多线程
ExecutorService executor01 = Executors.newCachedThreadPool();
  • 使用方式及参数配置详解
/**
 * 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 {@code 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
 */
 
 /**
  * 创建一个线程池,根据需要创建新线程,但是
  * 将重用之前构造的线程
  * 可用。这些池通常会提高性能执行许多短期异步任务的程序。
  * 调用{@code execute}将重用先前构造的代码
  * 线程(如果可用)。如果没有现有线程可用,则创建一个新的线程
  * 线程将被创建并添加到池中。具有
  * 未使用60秒被终止并从
  * 缓存。因此,一个保持空闲足够长的池将会
  * 不消耗任何资源。请注意具有相似的池
  * 属性,但不同的细节(例如超时参数)
  * 可以使用{@link ThreadPoolExecutor}构造函数创建。
  * @返回新建的线程池
 */
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}
  • 特点
1. 不会创建核心线程;
2. 把任务放到SynchronousQueue,offer方法不会阻塞,如果当前没有线程来拿这个任务,就会失败。
3. 会自动调节,如果某个线程一段时间不用。就会回收。更加的节省资源。
4. 它是一个可以无限扩大的线程池;它比较适合处理执行时间比较小的任务;corePoolSize为0,maximumPoolSize为无限大,意味着线程数量可以无限大;keepAliveTime为60S,意味着线程空闲时间超过60S就会被杀死;采用SynchronousQueue装等待的任务,这个阻塞队列没有存储空间,这意味着只要有请求到来,就必须要找到一条工作线程处理他,如果当前没有空闲的线程,那么就会再创建一条新的线程。
5. 4失败后创建空闲线程执行任务,因为空闲线程可以是Integer.MAX_VALUE,所以会成功。
  • 注意
1. 从工作特点可以看出SynchronousQueue不适合频繁提交任务,并且任务不适合执行时间过长
2. 高并发下会创建大量空闲线程导致OOM
  • 使用方式:
public static void main(String[] args) {
    ExecutorService executorService = Executors.newCachedThreadPool();
    for (int i = 0; i < 10; i++) {
        int temp = i;
        executorService.execute(new Runnable() {

            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "," + temp);
            }
        });
    }
}

pool-1-thread-1,0
pool-1-thread-2,1
pool-1-thread-3,2
pool-1-thread-4,3
pool-1-thread-5,4
pool-1-thread-6,5
pool-1-thread-7,6
pool-1-thread-8,7
pool-1-thread-9,8
pool-1-thread-10,9

可以看到,循环多少次,创建了多少线程

  • 线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程