本文将深入探讨Java线程池的方方面面,从线程状态介绍开始,逐步深入线程池的原理、Executors默认线程池的使用,自定义线程池的创建,ThreadPoolExecutor的参数详解,以及非默认任务拒绝策略的应用。最后,我们将通过一个小案例来展示如何使用线程池来提高程序效率。
Java线程的生命周期可以用以下状态来描述:
代码示例:
public class ThreadStateDemo {
public static void main(String[] args) {
// 创建一个新的线程
Thread thread = new Thread(() -> {
// 模拟线程运行逻辑
System.out.println("线程正在运行...");
try {
// 模拟阻塞操作
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程运行结束...");
});
// 启动线程
thread.start();
// 获取线程状态并打印
System.out.println("线程状态:" + thread.getState());
}
}
线程池是一种管理和复用线程的技术,它通过维护一组可重用线程来处理任务,避免频繁创建和销毁线程带来的性能开销。
基本原理:
优势:
java.util.concurrent.Executors 类提供了一些常用的线程池创建方法,包括:
代码示例:
public class ExecutorsDemo {
public static void main(String[] args) {
// 创建一个缓存线程池
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
// 创建一个固定线程数的线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
// 创建一个单线程化的线程池
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
// 创建一个可以执行延迟任务或周期性任务的线程池
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
}
}
可以使用 Executors 类中的 newFixedThreadPool(int nThreads) 方法来创建指定上限的线程池。
代码示例:
public class FixedThreadPoolDemo {
public static void main(String[] args) {
// 创建一个固定线程数为 5 的线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
// 提交任务到线程池
for (int i = 0; i < 10; i++) {
fixedThreadPool.execute(() -> {
// 模拟任务执行逻辑
System.out.println("线程池中的线程正在执行任务...");
});
}
// 关闭线程池
fixedThreadPool.shutdown();
}
}
java.util.concurrent.ThreadPoolExecutor 类是创建线程池的核心类,它提供了更加灵活的线程池配置方式。
代码示例:
public class ThreadPoolExecutorDemo {
public static void main(String[] args) {
// 创建一个线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // corePoolSize:核心线程数
10, // maximumPoolSize:最大线程数
60, // keepAliveTime:空闲线程存活时间
TimeUnit.SECONDS, // unit:空闲线程存活时间单位
new LinkedBlockingQueue<>(100), // workQueue:任务队列
new ThreadPoolExecutor.AbortPolicy() // handler:任务拒绝策略
);
// 提交任务到线程池
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
// 模拟任务执行逻辑
System.out.println("线程池中的线程正在执行任务...");
});
}
// 关闭线程池
executor.shutdown();
}
}
详解如下:
1.corePoolSize:核心线程的最大值,不能小于0 2.maximumPoolSize:最大线程数,不能小于等于0,maximumPoolSize >= corePoolSize 3.keepAliveTime: 空闲线程最大存活时间,不能小于0 4.unit:时间单位 5.workQueue:任务队列,不能为null 6.threadFactory:创建线程工厂,不能为null 7.handler:任务的拒绝策略,不能为null
代码示例:
public class ThreadPoolExecutorDemo {
public static void main(String[] args) {
// 创建一个线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // corePoolSize:核心线程数
10, // maximumPoolSize:最大线程数
60, // keepAliveTime:空闲线程存活时间
TimeUnit.SECONDS, // unit:空闲线程存活时间单位
new LinkedBlockingQueue<>(100), // workQueue:任务队列
new ThreadPoolExecutor.AbortPolicy() // handler:任务拒绝策略
);
// 提交任务到线程池
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
// 模拟任务执行逻辑
System.out.println("线程池中的线程正在执行任务...");
});
}
// 关闭线程池
executor.shutdown();
}
}
当任务队列已满且线程池中线程数量达到最大线程数时,会触发任务拒绝策略。ThreadPoolExecutor 类提供了一些默认的任务拒绝策略,也可以自定义任务拒绝策略。
代码示例:
// 使用 CallerRunsPolicy 作为拒绝策略
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5,
10,
60,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
new ThreadPoolExecutor.CallerRunsPolicy()
);
// 使用自定义拒绝策略
class MyRejectionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("任务被拒绝,执行自定义处理逻辑...");
}
}
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5,
10,
60,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
new MyRejectionHandler()
);
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolDownload {
public static void main(String[] args) {
// 创建一个固定线程数为 5 的线程池
ExecutorService executor = Executors.newFixedThreadPool(5);
// 要下载的文件 URL
String[] fileUrls = {
"https://www.example.com/file1.zip",
"https://www.example.com/file2.txt",
"https://www.example.com/file3.jpg",
"https://www.example.com/file4.pdf",
"https://www.example.com/file5.mp4"
};
// 提交下载任务到线程池
for (String fileUrl : fileUrls) {
executor.execute(() -> downloadFile(fileUrl));
}
// 关闭线程池
executor.shutdown();
}
// 下载文件
private static void downloadFile(String fileUrl) {
try {
URL url = new URL(fileUrl);
ReadableByteChannel rbc = Channels.newChannel(url.openStream());
FileOutputStream fos = new FileOutputStream(fileUrl.substring(fileUrl.lastIndexOf('/') + 1));
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
System.out.println("下载成功:" + fileUrl);
} catch (IOException e) {
System.err.println("下载失败:" + fileUrl + " - " + e.getMessage());
}
}
}
总结:
本文详细介绍了 Java 线程池的基础知识,从线程状态、线程池的基本原理、Executors默认线程池、自定义线程池的创建、ThreadPoolExecutor的参数详解,以及非默认任务拒绝策略等方面进行了深入讲解。最后,通过一个小案例展示了如何使用线程池来提高程序效率。希望本文能够帮助各位看官更好地理解和运用 Java 线程池,从而提升代码效率和性能。感谢各位看官的观看,下期见,谢谢~