1.简单介绍
线程池(Thread Pool)是一种用于管理和复用线程的技术,通过预先创建一定数量的线程并将它们组织起来,用于处理多个任务。简单来说就是用于管理线程对象的池子。它有着以下的优点
-
降低线程创建和销毁的开销。
-
控制并发线程数量。
-
提高响应速度。
-
提高系统稳定性。
2.如何使用
java中有以下几种等创建方式
- 通过Executors工厂类创建线程池:
ExecutorService executor = Executors.newFixedThreadPool(5);
- 通过ThreadPoolExecutor类直接创建线程池:
ThreadPoolExecutor executor = new ThreadPoolExecutor( 5, 10, 5000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>() );
- 通过ScheduledExecutorService创建定时任务线程池:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
- 通过ForkJoinPool创建工作窃取线程池(用于执行ForkJoinTask):
ForkJoinPool executor = new ForkJoinPool();
- 通过CompletableFuture的自定义线程池方式创建线程池:
ExecutorService executor = Executors.newFixedThreadPool(5); CompletableFuture<Void> future = CompletableFuture.runAsync(() -> { // 执行任务 }, executor);
Executors
Executors可以创建四种类型的线程池
-
newFixedThreadPool
固定大小线程池(newFixedThreadPool)它维护一定数量的线程。一旦所有线程都在忙碌,新任务会被添加到队列中,等待有空闲线程时执行。这种方法有助于限制资源使用并控制可以同时执行的任务数量。
public static ExecutorService newFixedThreadPool(int nThreads){
return new ThreadPoolExecutor(nThreads,nThreads,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
- newCachedThreadPool
可缓存线程池(newCachedThreadPool)它会根据需要动态地创建新的线程,如果有空闲线程可用,将会重用它们。当线程在60秒内没有被使用时,它们将被终止并从线程池中移除。这种线程池适合执行生命周期短的异步任务。
public static ExecutorService newCachedThreadPool(){
return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.MILLISECONDS,new SynchronousQueue<Runnable>());
}
- newSingleThreadExecutor
单一线程池(newSingleThreadExecutor) 它只包含一个工作线程来执行任务。这种线程池适合处理顺序执行的任务,一个接一个地执行,确保不会出现并发操作。当一个任务提交到 newSingleThreadExecutor线程池时,它会等待当前正在执行的任务完成之后再执行,这样可以避免多线程并发带来的问题。
public static ExecutorService newSingleThreadExecutor(){
return new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
- newScheduledThreadPool
定时线程池(newScheduledThreadPool) 它提供了一种便捷的方式来执行定时任务或周期性任务。newScheduledThreadPool允许我们指定任务的执行时间、间隔时间以及执行周期。该线程池会创建多个工作线程来执行任务,但它们会按照我们指定的时间进行调度,保证任务在指定的时间点或时间间隔内执行。
public static ExecutorService newCachedThreadPool(){
return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.MILLISECONDS,new SynchronousQueue<Runnable>());
}
ThreadPoolExecutor
hreadPoolExecutor 是一个线程池实现类,可以用于创建和管理线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyThreadPool {
public static void main(String[] args) {
// 创建一个固定大小的线程池,最多有3个线程同时运行任务
ExecutorService executor = Executors.newFixedThreadPool(3);
// 提交任务给线程池执行
executor.execute(new MyTask("Task 1"));
executor.execute(new MyTask("Task 2"));
executor.execute(new MyTask("Task 3"));
// 关闭线程池
executor.shutdown();
}
static class MyTask implements Runnable {
private String name;
public MyTask(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("Task " + name + " is running on thread " + Thread.currentThread().getName());
}
}
}
在上面的示例中,我们使用 Executors 工具类的 newFixedThreadPool 方法创建了一个固定大小为 3 的线程池,然后分别提交了三个任务给该线程池执行。每个任务会打印输出当前任务的名称以及正在运行该任务的线程的名称。最后,通过调用 shutdown() 方法关闭线程池。
ScheduledExecutorService
ScheduledExecutorService 是一个用于执行定时任务的接口,它是 ExecutorService 的子接口。ScheduledExecutorService 可以用来执行延迟任务或周期性任务,它提供了一系列方法来在指定延迟时间后执行任务,或在固定的时间间隔内定期执行任务。
import java.util.concurrent.*;
public class MyScheduledTask {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
// 延迟 1 秒后执行任务
ScheduledFuture<?> scheduledFuture = executor.schedule(new MyTask("Task 1"), 1, TimeUnit.SECONDS);
// 每隔 2 秒执行任务
executor.scheduleAtFixedRate(new MyTask("Task 2"), 0, 2, TimeUnit.SECONDS);
// 关闭线程池
executor.shutdown();
}
static class MyTask implements Runnable {
private String name;
public MyTask(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("Task " + name + " is running on thread " + Thread.currentThread().getName());
}
}
}
在上面的示例中,我们使用 Executors 工具类的 newScheduledThreadPool 方法创建了一个具有单线程的 ScheduledExecutorService。然后我们使用 schedule 和 scheduleAtFixedRate 方法分别创建了一个延迟 1 秒执行的任务和一个每隔 2 秒执行一次的周期性任务。
通过使用 ScheduledExecutorService,你可以很方便地执行定时任务和周期性任务,而不需要手动创建线程和管理任务的执行时间。