线程池是一种管理线程的技术,它可以在需要时创建线程,在不需要时回收线程,从而避免频繁创建和销毁线程带来的开销 线程池的主要作用是提高系统性能和资源利用率。通过使用线程池,我们可以避免频繁地创建和销毁线程,从而减少系统开销。线程池还可以控制线程的数量,从而避免由于线程过多而导致的资源竞争和性能下降。
使用线程池的原因包括:
-
提高性能:线程池可以减少线程的创建和销毁开销,提高程序的性能。
-
控制线程数量:线程池可以控制线程的数量,避免由于线程过多而导致的资源竞争和性能下降。
-
提高可靠性:线程池可以提供一些默认的线程管理功能,如异常处理、超时处理等,从而提高程序的可靠性。
实现方式:
1. Executors工厂类: Java标准库提供了Executors工厂类,可以通过他提供的静态方法来创建不同类型的线程池,比如 : newFixedThreadPool.newCachedThreadPool.newSingleThreadExecutor等,这些方法都会返回不同配置的线程池实例 2. 使用 Java 中的ThreadPoolExecutor类。可以通过该类的构造函数来指定线程池的核心参数,例如线程池大小、最大线程数、存活时间等
线程池的核心参数:
1.核心线程数 默认为1 2.最大线程数 默认为Integer.MAX_VALUE 3.超过核心线程的空闲线程存活时间 默认为60m 4.时间单位 5.任务队列长度 默认为Integer.MAX_VALUE 6.饱和策略(拒绝策略) 直接中断并抛出异常 忽略任务不抛异常(不推荐,容易造成数据丢失) 丢弃存活时间最长的任务 抛出异常让主线程处理(推荐) 7.线程工厂 创建线程
线程池的工作原理是什么?![](https://i-blog.csdnimg.cn/blog_migrate/330605199c5e2490fbc3b4f052b0ecf0.png)
1.先判断核心线程池中核心线程是否都在执行任务,如果不是,则创建线程执行当前任务,否则,核心线程都在执行任务,进入第二步 2.判断当前阻塞队列是否已满,如果未满,将当前任务存储在队列中,否则进入第三步 3.判断线程池中的非核心线程是否都在执行任务,如果不是,则创建一个非核心线程执行当前任务,否则按照饱和策略进行处理 !!!核心线程必须创建满5个以后才能复用核心线程(如果核心线程没有创建满,再来一个任务,不管其他核心线程有没有任务,都要新建一个核心线程来执行当前任务)
关闭线程池:
可以通过调用ThreadPoolExecutor
类的shutdown()
方法来关闭线程池。该方法会等待线程池中所有任务执行完成后,关闭线程池。也可以调用shutdownNow()
方法来立即关闭线程池,并尝试停止正在执行的任务。
设置线程池的大小:
设置线程池的大小需要考虑以下几个因素:
-
任务的性质:如果任务是 CPU 密集型的,则需要设置较小的线程池大小;如果任务是 I/O 密集型的,则需要设置较大的线程池大小。
-
硬件资源:根据硬件资源的限制来设置线程池大小,避免过多的线程导致资源竞争和性能下降。
-
任务的并发度:根据任务的并发度来设置线程池大小,避免任务过多而导致线程池无法及时处理。
线程池中的线程是如何复用的:
线程池中的线程是通过复用已经创建的线程来提高系统性能的。当线程执行完任务后,它不会被销毁,而是会被放回线程池中等待下一次任务。这样可以避免频繁地创建和销毁线程,从而减少系统开销。
处理线程池中的异常:
可以在提交任务时使用ExecutorService
类的submit()
方法,并在任务中捕获异常。如果任务执行过程中发生异常,异常会被传递给submit()
方法的调用方。也可以使用ExecutorService
类的execute()
方法提交任务,并使用ThreadPoolExecutor
类的afterExecute()
方法来处理任务执行过程中的异常。
池化技术:
池化技术的本质就是通过复用对象,连接等资源,减少对象/连接,垃圾回收(GC)的开销,适当的利用池化技术能够显著提高系统的性能和资源的利用率
连接池: 事先创建多个连接,将连接存放到一个容器中,便于后续使用,提高效率和复用性
线程池: 事先创建多个线程,将线程存放到一个容器中,便于后续使用,提高效率和复用性
对象池: Spring的IOC容器