缓存型线程池 newCachedThreadPool

[Q&A] newCachedThreadPool定义

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0,                                  设置为0,即corePool为空;
    							  Integer.MAX_VALUE,                  设置为Integer.MAX_VALUE,即是无界的。
                                  60L, TimeUnit.SECONDS,              意味着池中的空闲线程等待新任务的最长时间为60秒,空闲线程超过60秒后将会被终止。
                                  new SynchronousQueue<Runnable>());
}

[Q&A] newCachedThreadPool可能存在的问题
CachedThreadPool使用没有容量的SynchronousQueue作为线程池的工作队列,但CachedThreadPool的maximumPool是无界的。这意味着,如果主线程提交任务速度高于maximumPool中线程处理任务速度时,CachedThreadPool会不断创建新线程。极端情况下,CachedThreadPool会因为创建过多线程而耗尽CPU内存资源。


[Q&A] CachedThreadPoolexecute()方法的执行示意图如下图所示

在这里插入图片描述

# 1)首先执行SynchronousQueue.offer(Runnable task)
如果当前maximumPool中有空闲线程正在执行SynchronousQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS),那么主线程执行offer操作与空闲线程执行的poll操作配对成功,主线程把任务交给空闲线程执行,execute()方法执行完成;
否则执行下面的步骤2)。

# 2)当初始maximumPool为空,或者maximumPool中当前没有空闲线程时
没有线程执行SynchronousQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS)时CachedThreadPool会创建一个新线程执行任务,execute()方法执行完成。

# 3)在步骤2)中新创建的线程将任务执行完后,会执行SynchronousQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS)。
这个poll操作会让空闲线程最多在SynchronousQueue中等待60秒钟。如果60秒钟内主线程提交了一个新任务(主线程执行步骤1)),那么这个空闲线程将执行主线程提交的新任务;否则,这个空闲线程将终止。
由于空闲60秒的空闲线程会被终止,因此长时间保持空闲的CachedThreadPool不会使用任何资源。

[Q&A] CachedThreadPool的任务传递示意图

在这里插入图片描述

SynchronousQueue是一个没有容量的阻塞队列。每个插入操作必须等待另一个线程的对应移除操作,反之亦然。CachedThreadPool使用SynchronousQueue,把主线程提交的任务传递给空闲线程执行。
-----------------------------------------------------------------------------读书笔记摘自 书名:Java并发编程的艺术 作者:方腾飞;魏鹏;程晓明


常见用途

参考:Executor框架的成员


线程任务

public class Task implements Runnable {
    private final String name;

    public Task(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " → " + name + " Start Time = " + new Date());
        System.out.println(Thread.currentThread().getName() + " → " + name + " End   Time = " + new Date());
    }
}

缓存型线程池

public class cachedThreadPool {
    public static void main(String[] args) throws InterruptedException, ExecutionException {

        System.out.println(Thread.currentThread().getName() + "线程: Start at: " + new Date());

        ExecutorService exec = Executors.newCachedThreadPool();

        for (int i = 1; i < 10; i++) {
            System.out.println("添加了第" + i + "个任务类");
            Thread.sleep(2);
            exec.execute(new Task("线程名字" + i));
        }

        exec.shutdown();

        System.out.println(Thread.currentThread().getName() + " 线程: Finished all threads at:" + new Date());
    }
}

执行结果分析

执行结果
main线程: Start at: Fri May 19 20:55:45 CST 2023
添加了第1个任务类
添加了第2个任务类
添加了第3个任务类
添加了第4个任务类
添加了第5个任务类
pool-1-thread-1 → 线程名字1 Start Time = Fri May 19 20:55:45 CST 2023
pool-1-thread-4 → 线程名字4 Start Time = Fri May 19 20:55:45 CST 2023
pool-1-thread-2 → 线程名字2 Start Time = Fri May 19 20:55:45 CST 2023
pool-1-thread-3 → 线程名字3 Start Time = Fri May 19 20:55:45 CST 2023
pool-1-thread-1 → 线程名字1 End Time = Fri May 19 20:55:45 CST 2023
pool-1-thread-4 → 线程名字4 End Time = Fri May 19 20:55:45 CST 2023
pool-1-thread-3 → 线程名字3 End Time = Fri May 19 20:55:45 CST 2023
pool-1-thread-2 → 线程名字2 End Time = Fri May 19 20:55:45 CST 2023
添加了第6个任务类
pool-1-thread-3 → 线程名字5 Start Time = Fri May 19 20:55:45 CST 2023
pool-1-thread-3 → 线程名字5 End Time = Fri May 19 20:55:45 CST 2023
添加了第7个任务类
pool-1-thread-3 → 线程名字6 Start Time = Fri May 19 20:55:45 CST 2023
pool-1-thread-3 → 线程名字6 End Time = Fri May 19 20:55:45 CST 2023
添加了第8个任务类
pool-1-thread-3 → 线程名字7 Start Time = Fri May 19 20:55:45 CST 2023
pool-1-thread-3 → 线程名字7 End Time = Fri May 19 20:55:45 CST 2023
添加了第9个任务类
pool-1-thread-3 → 线程名字8 Start Time = Fri May 19 20:55:45 CST 2023
pool-1-thread-3 → 线程名字8 End Time = Fri May 19 20:55:45 CST 2023
pool-1-thread-3 → 线程名字9 Start Time = Fri May 19 20:55:45 CST 2023
pool-1-thread-3 → 线程名字9 End Time = Fri May 19 20:55:45 CST 2023
main 线程: Finished all threads at:Fri May 19 20:55:45 CST 2023
从控制台结果可以看出:
发现reuse的线程,线程池创建4个线程来 执行这9个任务
主线程的执行与线程池里的线程分开,有可能主线程结束了,但是线程池还在运行
放入线程池的线程并不一定会按其放入的先后而顺序执行
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当需要执行许多短时间的任务时,可以使用 `ExecutorService` 的 `newCachedThreadPool()` 方法创建一个线程池对象。该线程池会根据需要自动创建新的线程,并在空闲一定时间后自动回收不再使用的线程,因此适用于任务数量不确定或任务执行时间短的情况。 下面是一个使用 `newCachedThreadPool()` 方法创建线程池对象的示例代码: ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CachedThreadPoolExample { public static void main(String[] args) { // 创建一个可缓存线程池对象 ExecutorService executor = Executors.newCachedThreadPool(); // 提交多个任务 for (int i = 0; i < 10; i++) { executor.execute(new Task(i)); } // 关闭线程池 executor.shutdown(); } static class Task implements Runnable { private int taskId; public Task(int taskId) { this.taskId = taskId; } @Override public void run() { System.out.println("Task " + taskId + " is running."); } } } ``` 在以上示例代码中,我们首先使用 `Executors.newCachedThreadPool()` 方法创建了一个可缓存线程池对象 `executor`,并提交了多个任务。每个任务都是一个简单的输出语句,用于模拟一个短时间的任务。 最后,我们调用了 `executor.shutdown()` 方法关闭线程池。需要注意的是,一旦调用了 `shutdown()` 方法,线程池将不再接受新的任务,但已经提交的任务将继续执行直到完成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值