Java线程池深度解析:原理、拒绝策略与最佳实践

版权申诉
0 下载量 51 浏览量 更新于2024-07-19 收藏 1.69MB DOCX 举报
"这篇学习资料深入探讨了Java线程池的相关知识,涵盖了线程池的原理、Future模式的实现机制、execute与submit方法的区别、SynchronousQueue的工作方式、拒绝策略,以及线程池在实际使用中可能遇到的问题和解决方案。此外,资料还涉及到了线程池的参数设置、Tomcat和Netty自定义线程池的原因,以及异常处理策略。" 1:线程池原理 线程池通过维护一组可重用的工作线程来提高程序性能,避免频繁创建和销毁线程的开销。在Java中,`ThreadPoolExecutor`是实现线程池的核心类。线程池中的线程通过一个无限循环来接收并执行任务,当线程执行异常时,异常会被捕获并抛出,导致线程终止,同时线程从工作集合中移除。 2:Future模式get()和get(timeout)实现 Future模式提供了一种异步计算的结果获取方式。`get()`和`get(timeout)`方法会在调用者线程阻塞,直到任务完成或达到指定超时时间。当任务完成后,调用者可以获取结果。 3:execute与submit方法区别 `execute()`方法用于提交`Runnable`任务,而`submit()`方法可以提交`Callable`任务,返回一个`Future`对象,使得我们能查询任务状态和获取结果。`submit()`内部实际上是将`Callable`包装成`FutureTask`,再调用`execute()`。 4:SynchronousQueue SynchronousQueue是一个特殊的阻塞队列,它不存储元素,任务的提交必须立即有另一个线程来接手。如果无法找到接手线程,任务提交会失败。 5:拒绝策略 `CallerRunsPolicy`是线程池的一种拒绝策略,当线程池无法处理新任务时,会由调用`execute`的线程来执行这个任务,以此来控制任务的提交速度。 6:线程池的主要参数 线程池的主要参数包括核心线程数(`corePoolSize`)、最大线程数(`maximumPoolSize`)、线程存活时间(`keepAliveTime`)和工作队列(`WorkQueue`)。 7:线程池默认线程及核心线程数 线程池创建时,默认线程数取决于实现,通常为0。如果核心线程数为10且达到,即使在保持存活时间后,只要仍有任务提交,核心线程数不会减少。除非显式调用`setCorePoolSize(0)`。 8:Tomcat自定义线程池原因 Tomcat使用自定义线程池是因为JDK自带的线程池可能无法满足其特定需求,如更精细的线程管理、更好的性能优化或与Servlet容器的集成。 9:ThreadPoolExecutor与ExecutorCompletionService的区别 `ExecutorCompletionService`是一个辅助类,它结合了`Executor`和`Future`,使得批量异步任务可以按完成顺序处理结果,而`ThreadPoolExecutor`则专注于任务的执行。 10:线程池异常处理 线程池中的线程如果抛出异常,对于`execute`提交的任务,异常会被丢弃,线程继续执行下一个任务。而对于`submit`提交的任务,异常会封装在`Future`的`get`方法中抛出。异常线程不会直接影响其他线程,但可能会导致线程池的拒绝策略被触发。 11:Netty不使用JDK Future Netty选择不使用JDK的`Future`主要是因为Netty的异步模型更加强大和灵活,它使用了自己的`ChannelFuture`和`Promise`,这些类提供了更丰富的功能,如链式调用和事件通知。