面试题答案
一键面试- 默认线程池:
CompletableFuture.runAsync
方法默认使用的是ForkJoinPool.commonPool()
线程池。这是一个公共的ForkJoinPool
实例,其线程数量通常为Runtime.getRuntime().availableProcessors()
- 1(但实际数量可能会根据负载情况调整)。这个线程池适用于很多通用的异步任务场景。
- 自定义线程池:
- 可以通过重载
runAsync
方法来传入自定义线程池。例如:
ExecutorService executor = Executors.newFixedThreadPool(10); CompletableFuture.runAsync(() -> { // 异步任务代码 System.out.println("异步任务执行中"); }, executor);
- 这里创建了一个固定大小为10的线程池
executor
,并将其作为参数传递给runAsync
方法,这样异步任务就会在这个自定义线程池中执行。
- 可以通过重载
- 自定义线程池的优势:
- 资源控制:可以根据业务需求精确控制线程数量。比如对于I/O密集型任务,可以设置较多的线程;对于CPU密集型任务,可以设置较少的线程,避免资源过度消耗。
- 隔离性:不同的业务模块可以使用不同的线程池,防止某个模块的任务过多或异常导致整个系统的线程资源耗尽,影响其他模块的正常运行。
- 优先级:可以创建支持任务优先级的线程池,确保重要的异步任务优先执行。
- 需要注意的点:
- 线程池大小:如果线程池设置过大,会导致过多的上下文切换开销,占用过多系统资源;如果设置过小,会导致任务排队等待,影响系统性能。需要根据任务的类型(CPU密集型、I/O密集型等)和系统资源情况进行合理配置。
- 线程池关闭:需要妥善处理线程池的关闭。如果在应用程序关闭时,没有正确关闭自定义线程池,可能会导致异步任务无法正常结束,甚至造成内存泄漏等问题。通常可以在应用程序关闭时调用
executor.shutdown()
和executor.awaitTermination()
方法来优雅关闭线程池。 - 异常处理:在自定义线程池中执行异步任务时,需要注意异常的捕获和处理。由于异步任务的特性,如果不进行适当处理,异常可能不会被及时发现,导致程序出现难以排查的错误。可以通过
CompletableFuture
的exceptionally
等方法来处理异步任务中的异常。