万字总结最全Java线程池ThreadPoolExecutor面试题(四)

简介: 万字总结最全Java线程池ThreadPoolExecutor面试题(四)

单线程池

  • newSingleThreadExecutor创建

image.png

池中保持一个线程,最多也只有一个线程,也就是说这个线程池是顺序执行任务的,多余的任务就在队列中排队。

固定线程池

  • newFixedThreadPool(nThreads)创建

image.png

池中保持nThreads个线程,最多也只有nThreads个线程,多余的任务也在队列中排队。

image.png

image.png

线程数固定且线程不超时。

缓存线程池

  • newCachedThreadPool()创建

image.png

池中不保持固定数量的线程,而是按需创建,最多可创建Integer.MAX_VALUE个线程,这已大大超过目前任何os允许的线程数。

空闲的线程最多保持60s,多余的任务在SynchronousQueue等待。

适用场景
  1. 耗时较短的任务
  2. 任务处理速度 > 任务提交速度 ,这样才能保证不会不断创建新的进程,避免内存被占满。


线程池中的线程是被线程池缓存了的,即:


线程没有任务执行时,便处于空闲状态,处于空闲状态的线程并不会被立即销毁(会被缓存),只有当空闲时间超出一段时间(默认60s)后,线程池才会销毁该线程(相当于清除过时缓存)

新任务到达后,线程池首先会让被缓存住的线程(空闲状态)去执行任务,若无可用线程(无空闲线程),便会创建新的线程。


为什么使用SynchronousQueue()?

因为单线程池和固定线程池中,线程数量有限,因此提交的任务需要在LinkedBlockingQueue队列中等待空闲线程。

而缓存线程池中,线程数量几乎无限(上限为Integer.MAX_VALUE),因此提交的任务只需要在SynchronousQueue队列中同步移交给空余线程即可。

固定调度线程池

  • newScheduledThreadPool(n)创建

image.png

image.png

池中保持n个线程,多余的任务在DelayedWorkQueue中等待。

有一项技术可以缓解执行时间较长任务造成的影响,即限定任务等待资源的时间,而不要无限的等待.

先看第一个例子,测试单线程池、固定线程池和缓存线程池(注意增加和取消注释):

public class ThreadPoolExam {
    public static void main(String[] args) {
        //first test for singleThreadPool
        ExecutorService pool = Executors.newSingleThreadExecutor();
        //second test for fixedThreadPool
//        ExecutorService pool = Executors.newFixedThreadPool(2);
        //third test for cachedThreadPool
//        ExecutorService pool = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            pool.execute(new TaskInPool(i));
        }
        pool.shutdown();
    }
}
class TaskInPool implements Runnable {
    private final int id;
    TaskInPool(int id) {
        this.id = id;
    }
    @Override
    public void run() {
        try {
            for (int i = 0; i < 5; i++) {
                System.out.println("TaskInPool-["+id+"] is running phase-"+i);
                TimeUnit.SECONDS.sleep(1);
            }
            System.out.println("TaskInPool-["+id+"] is over");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

如图为排查底层公共缓存调用出错时的截图

  • 有意义的线程命名

网络异常,图片无法展示
|

绿色框采用自定义的线程工厂,明显比蓝色框默认的线程工厂创建的线程名称拥有更多的额外信息:如调用来源、线程的业务含义,有助于快速定位到死锁、StackOverflowError 等问题。

Executors类提供的一些快捷声明线程池的方法虽然简单,但隐藏了线程池的参数细节。因此,使用线程池时,我们一定要根据场景和需求配置合理的线程数、任务队列、拒绝策略、线程回收策略,并对线程进行明确的命名方便排查问题。


目录
相关文章
|
2月前
|
Java 调度 数据库
Java并发编程:深入理解线程池
在Java并发编程的海洋中,线程池是一艘强大的船,它不仅提高了性能,还简化了代码结构。本文将带你潜入线程池的深海,探索其核心组件、工作原理及如何高效利用线程池来优化你的并发应用。
|
2月前
|
存储 监控 Java
Java多线程优化:提高线程池性能的技巧与实践
Java多线程优化:提高线程池性能的技巧与实践
72 1
|
29天前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
1月前
|
消息中间件 前端开发 NoSQL
面试官:线程池遇到未处理的异常会崩溃吗?
面试官:线程池遇到未处理的异常会崩溃吗?
62 3
面试官:线程池遇到未处理的异常会崩溃吗?
|
1月前
|
消息中间件 前端开发 NoSQL
面试官:如何实现线程池任务编排?
面试官:如何实现线程池任务编排?
27 1
面试官:如何实现线程池任务编排?
|
1月前
|
Java 调度 开发者
Java并发编程:深入理解线程池
在Java的世界中,线程池是提升应用性能、实现高效并发处理的关键工具。本文将深入浅出地介绍线程池的核心概念、工作原理以及如何在实际应用中有效利用线程池来优化资源管理和任务调度。通过本文的学习,读者能够掌握线程池的基本使用技巧,并理解其背后的设计哲学。
|
1月前
|
缓存 监控 Java
Java中的并发编程:理解并应用线程池
在Java的并发编程中,线程池是提高应用程序性能的关键工具。本文将深入探讨如何有效利用线程池来管理资源、提升效率和简化代码结构。我们将从基础概念出发,逐步介绍线程池的配置、使用场景以及最佳实践,帮助开发者更好地掌握并发编程的核心技巧。
|
1月前
|
缓存 监控 Java
java中线程池的使用
java中线程池的使用
|
2月前
|
Java
【多线程面试题二十五】、说说你对AQS的理解
这篇文章阐述了对Java中的AbstractQueuedSynchronizer(AQS)的理解,AQS是一个用于构建锁和其他同步组件的框架,它通过维护同步状态和FIFO等待队列,以及线程的阻塞与唤醒机制,来实现同步器的高效管理,并且可以通过实现特定的方法来自定义同步组件的行为。
【多线程面试题二十五】、说说你对AQS的理解
|
14天前
|
Java 数据中心 微服务
Java高级知识:线程池隔离与信号量隔离的实战应用
在Java并发编程中,线程池隔离与信号量隔离是两种常用的资源隔离技术,它们在提高系统稳定性、防止系统过载方面发挥着重要作用。
13 0

热门文章

最新文章