赶紧收藏!2024 年最常见 100道 Java 基础面试题(二十三)

上一篇地址:赶紧收藏!2024 年最常见 100道 Java 基础面试题(二十二)-CSDN博客

四十五、线程池都有哪些状态?

在Java中,线程池(ThreadPoolExecutor)的状态与Java的线程状态是不同的。线程池的状态主要指的是线程池的生命周期状态,它定义了线程池对提交的任务的处理方式。以下是线程池的几种状态:

  1. 运行(Running)

    • 在这个状态下,线程池可以接受新的任务,也可以处理阻塞队列中的等待任务。
  2. 关闭(Shutting Down)

    • 线程池的shutdown()方法被调用后,线程池进入关闭状态。此时,线程池不再接受新任务,但会处理阻塞队列中的已提交任务。
  3. 停止(Stop)

    • 当调用线程池的shutdownNow()方法时,线程池会尝试停止处理等待任务,并尝试停止所有正在执行的任务。此时线程池的状态是停止。shutdownNow()会尝试立即停止所有活动执行的任务。
  4. 阻塞(Blocked)

    • 线程池的状态并不包括阻塞,但如果所有线程都忙碌,且队列已满,那么线程池在处理任务时可能会表现出阻塞的特性。
  5. 终止(Terminated)

    • 线程池在执行完所有提交的任务后,可以变为终止状态。线程池的isTerminating()方法可以用来判断线程池是否在终止过程中。
  6. 等待(Waiting)

    • 线程池的状态并不包括等待,但线程池中的线程在没有任务可执行时,会处于等待状态,直到有新的任务到来或线程池被关闭。

线程池状态转换和相关方法

  • 启动:当线程池被创建,并且至少有一条线程在运行时,线程池就处于运行状态。
  • 关闭:调用shutdown()方法会关闭线程池,不再接受新任务,但会处理队列中的等待任务。
  • 立即停止:调用shutdownNow()方法会让线程池尝试立即停止,并中断正在执行的任务。
  • 终止:当线程池中的所有任务都已完成,且所有线程都已停止时,线程池变为终止状态。

示例代码

import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;

public class ThreadPoolStatusExample {
    public static void main(String[] args) {
        ExecutorService executor = new ThreadPoolExecutor(
            3, // core pool size
            10, // maximum pool size
            60L, // keep-alive time
            TimeUnit.SECONDS, // time unit
            new LinkedBlockingQueue<Runnable>() // work queue
        );

        // 关闭线程池,不再接受新任务,但处理等待任务
        executor.shutdown();

        // 尝试立即停止,中断正在执行的任务
        executor.shutdownNow();

        // 判断线程池是否终止
        ((ThreadPoolExecutor) executor).isTerminating();
    }
}

总结

  • 线程池的状态反映了线程池的生命周期,从运行到关闭,再到终止。
  • 线程池的状态转换由相应的线程池控制方法触发,如shutdown()shutdownNow()
  • 了解线程池的状态对于正确管理线程池和任务调度非常重要。

四十六、线程池中submit()execute()方法有什么区别?

在Java的java.util.concurrent包中,ThreadPoolExecutor类提供了两个关键的方法来提交任务:submit()execute()。这两个方法都用于向线程池提交任务,但它们之间存在一些差异:

  1. 返回类型

    • submit()方法的返回类型是Future<?>,它允许你获取任务执行的结果,或者在任务完成前取消任务。
    • execute()方法不接受返回值,也不提供Future对象,因此你无法通过它来获取任务的执行结果或取消任务。
  2. 任务结果

    • 使用submit()方法,你可以获取任务执行的结果,特别是当任务是一个Callable对象时。这使得submit()适用于那些需要返回值的异步任务。
    • execute()方法主要用于那些不需要返回结果的Runnable任务。
  3. 异常处理

    • submit()方法中,如果任务在执行过程中抛出异常,异常会被捕获并作为Future的一部分,你可以通过调用Future.get()方法来获取这个异常。
    • execute()方法中,如果任务抛出异常,异常会由线程池内部处理,除非线程池的RejectedExecutionHandler有特殊的处理逻辑,否则你无法直接感知到这个异常。
  4. 任务调度

    • submit()方法可以用于执行CallableRunnable任务,而execute()方法只能执行Runnable任务。
  5. 线程池关闭后的行为

    • 当线程池关闭后,submit()方法会抛出RejectedExecutionException,因为它尝试向线程池提交任务。
    • execute()方法在线程池关闭后的行为取决于线程池的状态和具体实现,但通常也会拒绝新任务的提交。
  6. 示例代码

  7. import java.util.concurrent.*;
    
    public class ThreadPoolSubmitExecuteExample {
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(3);
    
            // 使用submit()提交任务
            Future<?> future = executorService.submit(() -> {
                System.out.println("Task submitted with a Future");
            });
            // 可以调用future.get()来获取任务执行结果或异常
    
            // 使用execute()提交任务
            executorService.execute(() -> {
                System.out.println("Task executed without a Future");
            });
            // 不能获取任务执行结果或取消任务
    
            executorService.shutdown();
        }
    }

总结

  • submit()方法适用于需要获取任务结果或对任务进行取消的场景,它返回一个Future对象。
  • execute()方法适用于不需要任务结果的简单任务执行,它不返回任何内容。
  • 在设计线程池任务提交逻辑时,应根据任务是否需要返回结果或是否需要支持任务取消来选择合适的方法。
  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很高兴回答你关于Java基础面试题。下面是一些常见Java基础面试题,供你参考: 1. 什么是Java? - Java是一种面向对象的编程语言,具有跨平台特性,由Sun Microsystems(现在是Oracle)开发。 2. Java的特点是什么? - Java具有面向对象、跨平台、健壮性、安全性、可移植性、多线程等特点。 3. Java中的自动装箱和拆箱是什么意思? - 自动装箱是指将基本类型自动转换为对应的包装类型,如int自动转换为Integer。 - 自动拆箱是指将包装类型自动转换为对应的基本类型,如Integer自动转换为int。 4. Java中的重载和重写有什么区别? - 方法重载(Overload)指在一个类中可以定义多个方法名相同但参数类型或个数不同的方法。 - 方法重写(Override)指子类重新定义了父类中已有的方法,要求方法名、参数类型和个数完全相同。 5. Java中的异常处理机制是什么? - Java中采用try-catch-finally来处理异常。try块中包含可能抛出异常的代码,catch块用于捕获和处理异常,finally块用于释放资源。 6. String、StringBuilder和StringBuffer的区别是什么? - String是不可变的字符串,每次修改都会生成新的对象,适用于字符串不经常变化的情况。 - StringBuilder是可变的字符串,适用于频繁修改字符串内容的情况,但不是线程安全的。 - StringBuffer也是可变的字符串,与StringBuilder功能相似,但是是线程安全的。 以上是一些常见Java基础面试题,希望能对你有所帮助。如果你还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值