线程池相关面试题

一、什么是线程池?

线程池是用来管理和复用线程的工具,他可以减少线程的创建和销毁开销。

在java中,ThreadPoolExecutor是线程池的核心实现,它通过核心线程数、最大线程数、 任务队列和拒绝策略来控制线程的创建和执行。

举个例子:就像你开了一家餐厅,线程池就相当于固定数量的服务员,顾客(任务)来了就安排空闲的服务员(线程)处理,避免了频繁招人和解雇的成本。

二、线程池的工作原理

任务提交 ----> 核心线程执行 ----> 任务队列缓存 -----> 非核心线程执行 ----> 拒绝策略处理

1、线程池通过submit()或 execute()提交任务 
ExecutorService threadPool = Executors.newFixedThreadPool(5);
threadPool.submit(() -> {
    System.out.println(Thread.currentThread().getName() + "\t" + "办理业务");
});
2、线程池会先创建核心线程来执行任务
if (workerCountOf(c) < corePoolSize) {
    if (addWorker(command, true)) {
        return;
    }
}
3、如何核心线程都在忙,任务就会被放入队列中
workQueue.offer(task);
4、如何任务队列已满,且当前线程数量小于最大线程数量,线程池就会创建新的线程(非核心线程)来处理任务
if (!addWorker(command, false))
5、如果线程池中的线程数量已经达到最大线程数,且任务队列已满,线程池就会执行拒绝策略
handler.rejectedExecution(command, this);

三、线程池的拒绝策略有哪些?

  1. AbortPolicy:默认的拒绝策略,会抛 RejectedExecutionException 异常。 ----> 我们系统瘫痪了

  2. CallerRunsPolicy:让提交任务的线程自己来执行这个任务,也就是调用 execute 方法的线程。 -----> 谁叫你来的找谁去

  3. DiscardOldestPolicy:等待队列会丢弃队列中最老的一个任务,也就是队列中等待最久的任务,然后尝试重新提交被拒绝的任务。 -----> 你去对立加个塞

  4. DiscardPolicy:丢弃被拒绝的任务,不做任何处理也不抛出异常。 -----> 你改天再来吧

四、创建线程池的七大参数

  • corePoolSize:核心线程数,长期存活,执行任务的主力。

  • maximumPoolSize:线程池允许的最大线程数。

  • workQueue:任务队列,存储等待执行的任务。

  • handler:拒绝策略,任务超载时的处理方式。也就是线程数达到 maximumPoolSiz,任务队列也满了的时候,就会触发拒绝策略。

  • threadFactory:线程工厂,用于创建线程,可自定义线程名。

  • keepAliveTime:非核心线程的存活时间,空闲时间超过该值就销毁。

  • unit:keepAliveTime 参数的时间单位:

    • TimeUnit.DAYS; 天

    • TimeUnit.HOURS; 小时

    • TimeUnit.MINUTES; 分钟

    • TimeUnit.SECONDS; 秒

    • TimeUnit.MILLISECONDS; 毫秒

    • TimeUnit.MICROSECONDS; 微秒

    • TimeUnit.NANOSECONDS; 纳秒

五、线程池提交execute和submit有什么区别?

execute 方法没有返回值,适用于不关心结果和异常的简单任务。

threadsPool.execute(new Runnable() {
    @Override public void run() {
        System.out.println("execute() 方法提交的任务");
    }
});

submit 有返回值,适用于需要获取结果或处理异常的场景。

Future future = executor.submit(harReturnValuetask);
try { Object s = future.get(); } 
catch (InterruptedException e | ExecutionException e) {
    // 处理无法执行任务异常
} finally {
    // 关闭线程池 executor.shutdown();
} 
  

六、线程池的几种状态

状态 描述
新建状态 当线程对象被创建后,即进入新建状态
就绪状态 当调用了线程对象的star() 方法,即进入就绪状态
运行状态 当CPU开始调度处于就绪状态的线程时,即进入运行状态
阻塞状态 处于运行状态中的线程因为某种原因,暂时放弃CPU的使用,即进入阻塞状态
死亡状态 线程执行完了或者因为异常退出了run()方法,该线程结束了生命周期,即死亡状态

你可能感兴趣的:(java)