目录
线程池简介
线程池:一种使用线程的模式,存放了很多可以复用的线程,对线程统一管理。我们可以使用new的方式去创建线程,但若是并发线程太高,每个线程执行时间不长,这样频繁的创建销毁线程是比较耗费资源的,线程池就是用来解决此问题的。
线程池的作用
线程池是一种用于管理和复用线程的机制,具有以下作用:
降低资源消耗:线程的创建和销毁是一个开销较大的过程,使用线程池可以避免重复创建线程,减少了创建和销毁线程所带来的资源消耗,提高了系统的性能和效率。
提高响应速度:线程池中的线程在执行任务时,可以并行处理多个任务,提高了系统的并发性和响应速度。线程池能够根据当前的负载情况自动调整线程数量,确保任务能够尽快得到处理。
控制并发数:线程池可以限制系统中并发线程的数量,在高并发的情况下,通过控制线程数量可以避免系统资源被过度占用而导致系统崩溃或变得不可响应。
提供线程管理和调度:线程池可以统一管理和调度线程的创建、销毁和执行,简化了线程的管理工作。线程池可以根据需要动态调整线程数量,并提供监控和统计信息,方便对线程的状态和执行情况进行监控和管理。
支持任务队列:线程池通常配备一个任务队列,用于存储还未被执行的任务。当线程池中的线程空闲时,可以从任务队列中获取新任务进行执行,避免任务丢失或阻塞。
通过使用线程池,可以提高系统的并发性、响应速度和资源利用率,合理管理线程,并减轻开发人员对线程的手动管理负担。线程池已经成为了现代多线程编程的重要工具。
Executors四种创建线程池的方式
在Java中,可以使用以下几种方式来创建线程池:
1. Executors.newFixedThreadPool(int nThreads):创建一个固定大小的线程池。该线程池会创建指定数量的线程,并且如果有空闲线程,会一直复用它们,直到线程池被显式地关闭。
2. Executors.newCachedThreadPool():创建一个可缓存的线程池。该线程池会根据需要自动创建新的线程,如果有可用的空闲线程,则会复用它们;如果没有可用线程,则会创建新的线程。适用于执行大量短期异步任务的场景,线程数会根据任务的数量自动调整。
3. Executors.newSingleThreadExecutor():创建一个单线程化的线程池。该线程池只会创建一个工作线程来执行任务,保证任务按照指定顺序(FIFO、LIFO、优先级等)执行。
4. Executors.newScheduledThreadPool(int corePoolSize):创建一个支持定时和周期性任务执行的线程池。该线程池可以执行定时任务或者以固定频率执行任务。
这些方法都是通过 `Executors` 类提供的静态方法来创建线程池,并返回一个实现了 `ExecutorService` 接口的线程池对象。
另外,还可以使用 `ThreadPoolExecutor` 类进行更加灵活地创建线程池,可以自定义线程池的各种参数,如核心线程数、最大线程数、任务队列等。
例如:
int corePoolSize = 10;
int maximumPoolSize = 20;
long keepAliveTime = 60; // 单位为秒
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(100);
ExecutorService threadPool = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
workQueue
);
这里使用 `ThreadPoolExecutor` 类来创建一个具有核心线程数为10,最大线程数为20,空闲线程的存活时间为60秒,任务队列使用了一个容量为100的有界队列的线程池。
无论使用哪种方式创建线程池,都需要根据业务需求选择适当的线程池类型,并根据实际情况调整线程池的大小和其他参数,以确保线程池能够高效地执行任务。最后,记得在合适的时机关闭线程池,防止资源泄漏。
要创建一个 ThreadPoolExecutor
线程池
要创建一个
ThreadPoolExecutor
线程池,你需要使用以下构造函数:
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
下面是对每个参数的详细说明:
corePoolSize
:指定线程池中保持活跃的核心线程数。即使这些线程处于空闲状态,它们也不会被销毁。当有新任务提交时,线程池中的核心线程将被优先使用。
maximumPoolSize
:指定线程池中允许存在的最大线程数。当任务数量超过corePoolSize
且任务队列已满时,线程池将创建新的线程来处理任务,但数量不会超过maximumPoolSize
。
keepAliveTime
:指定非核心线程在空闲状态下的存活时间。如果线程池中的线程数超过corePoolSize
,并且空闲时间超过keepAliveTime
,多余的线程将被终止,直到线程数等于corePoolSize
。
unit
:指定keepAliveTime
的时间单位,可以是秒、毫秒、微秒等。
workQueue
:用于保存等待执行的任务的阻塞队列。当线程池中的线程都在忙碌时,新任务将被放入任务队列等待执行。下面是一个示例,演示如何使用
ThreadPoolExecutor
创建线程池:
import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) {
int corePoolSize = 5;
int maximumPoolSize = 10;
long keepAliveTime = 60;
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(100);
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue
);
// 执行任务
threadPool.execute(() -> {
// 任务逻辑
});
// 关闭线程池(在不再需要执行任务时调用)
threadPool.shutdown();
}
}
上述示例中,我们创建了一个核心线程数为5,最大线程数为10,空闲线程的存活时间为60秒的线程池。任务队列使用了一个容量为100的有界阻塞队列。然后,我们通过
execute
方法向线程池提交一个任务,并在最后调用shutdown
方法关闭线程池。请注意,在实际使用中,你需要根据具体的业务需求和系统资源情况来调整线程池的参数,以确保线程池能够高效地处理任务。