第21讲 | Java并发类库提供的线程池有哪几种? 分别有什么特点?
该思维导图由 AI 生成,仅供参考
典型回答
- 深入了解
- 翻译
- 解释
- 总结
Java并发编程中的线程池是一种重要的工具,提供了多种类型的线程池,适用于不同类型的任务处理。这些线程池具有高度的可调节性和灵活性,可以根据实际需求配置不同的参数,创建出行为大相径庭的线程池。然而,在使用线程池时需要注意避免任务堆积、过度扩展线程、线程泄漏和死锁等同步问题,以及合理选择线程池大小。虽然大多数情况下使用Executors提供的静态工厂方法已经足够,但深入学习Executor框架的主要内容、线程池和相关并发工具类型的理解,以及实践中常见问题的诊断思路,都是值得深入学习的内容。文章还提到了在解决大负载问题时,除了调整线程池外,架构上的改变也能更好地解决问题。因此,合理使用线程池需要根据自身应用特点进行选择。整体而言,本文介绍了Java中不同类型的线程池及其使用注意事项,对于想要深入了解并发编程的读者具有一定的参考价值。
《Java 核心技术面试精讲》,新⼈⾸单¥59
全部留言(37)
- 最新
- 精选
- I am a psycho通过看源码可以得知,core和max都是1,而且通过FinalizableDelegatedExecutorService进行了包装,保证线程池无法修改。同时shutdown方法通过调用interruptIdleWorkers方法,去停掉没有工作的线程,而shutdownNow方法是直接粗暴的停掉所有线程。无论是shutdown还是shutdownNow都不会进行等待,都会直接将线程池状态设置成shutdown或者stop,如果需要等待,需要调用awaitTernination方法。查找了一下threadFactory的使用,只找到了在worker创建的时候,用来初始化了线程。
作者回复: 不错,很棒的总结; 我问threadFactory次数,其实是问worker都在什么情况下会被创建,比如,比较特别的,任务抛异常时;随便自定义一个threadfactory,模拟提交任务就能体会到
2018-06-23364 - 李二木我觉得还有一点很重要,就是放在线程池中的线程要捕获异常,如果直接抛出异常,每次都会创建线程,也就等于线程池没有发挥作用,如果大并发下一直创建线程可能会导致JVM挂掉。最近遇到的一个坑
作者回复: 任务出异常是要避免
2018-06-23551 - 约书亚疑问,为什么当初sun的线程池模式要设计成队列满了才能创建非核心线程?类比其他类似池的功能实现,很多都是设置最小数最大数,达到最大数才向等待队列里加入,比如有的连接池实现。
作者回复: Doug Lea这个实现基本是工业标准了,除非特定场景需求
2018-06-231027 - 沈琦斌老师,我想问的是cache的线程池大小是1,每次还要新创建,那和我自己创建而不用线程池有什么区别?
作者回复: 你是说cachedthreadpool?那个大小是浮动的,不是1;如果说single,executorservice毕竟还提供了工作队列,生命周期管理,工作线程维护等很多事,还是要高效
2018-06-2815 - 饭粒写了个简单demo玩了下。 创建线程池会初始化线程工厂,工作线程是在提交任务的创建的。工作线程在执行任务中抛出异常,再次提交任务会又新建工作线程。newFixedThreadPool 正常执行任务时会优先创建线程已达到核心线程数,不会优先复用空闲工作线程。 ``` /** * 线程池工作线程执行任务抛出异常 */ @Test public void test03() throws InterruptedException { // java.util.concurrent.Executors.DefaultThreadFactory.DefaultThreadFactory 构造线程工厂 ExecutorService executorService = Executors.newCachedThreadPool(); Runnable task = new Runnable() { @Override public void run() { System.out.println("hello world"); // 抛出异常 throw new RuntimeException(); } }; executorService.execute(task); // 提交任务通过 DefaultThreadFactory.newThread() 创建线程 TimeUnit.SECONDS.sleep(2); // 前一个工作线程在执行任务中抛出异常,再提交任务又会新建工作线程 executorService.execute(task); TimeUnit.SECONDS.sleep(3); } ```
作者回复: 实践是好习惯
2019-01-15211 - 王磊core和max应该都是1。验证的方法是自己写一个Threadlocal, 里面有相应创建线程的日志,然后把它传入创建线程池。
作者回复: core和Max源码或者逻辑分析都很清楚;而创建线程次数理论上是不确定的,比如任务执行中抛异常,就要重新创建worker
2018-06-256 - GK java线程池到底需不需要关闭
作者回复: 通常建议明确关闭,要看具体场景,我们的应用对于关闭本身是如何定义,有没有要求,什么时机触发,需要保证优雅的退出吗?
2019-01-265 - 欣杨老师,我照着文章翻看源码,下面那块是不是不太对? ---------------- Executors 目前提供了 5 种不同的线程池创建配置: newSingleThreadExecutor,它创建的是个 FinalizableDelegatedExecutorService newSingleThreadScheduledExecutor 创建的是 ScheduledThreadPoolExecutor
作者回复: 谢谢指出
2018-07-0425 - 镰仓听了一段时间课程,质量很高。我的需求是android JavaVM
作者回复: android我并没有特别的经验,尽管很多方面是通用的
2018-06-283 - 灰飞灰猪不会灰飞.烟灭老师 放入队列中的线程是直接调用start方法还是把队列中的线程放入线程工厂,让线程工厂执行? 另外,怎么判断一个线程是否执行完成呢?(只有执行完成才返回结果)谢谢老师
作者回复: 工厂是创建线程;执行完成通常是说任务,而不是线程,任务才是我们关心的;可以用Future
2018-06-252