1. Java线程池的执行流程
Java线程池通过ThreadPoolExecutor类实现,其执行流程概括为以下步骤:
-
任务提交:通过execute()或submit()方法提交任务到线程池。
-
任务分配:
- 如果当前活动线程数小于核心线程数,直接创建新线程执行任务。
- 如果核心线程数已满,但任务队列未满,任务会被加入队列等待。
- 如果队列也满了,且当前线程数小于最大线程数,会创建非核心线程执行任务。
- 如果线程数达到最大且队列也满,触发拒绝策略。
-
线程复用:任务完成后,线程不会立即销毁,而是会复用执行下一个任务,直到线程空闲时间超过设定值才可能被回收。
-
关闭线程池:调用shutdown()或shutdownNow(),前者不允许提交新任务但会等待现有任务完成,后者尝试取消所有任务并关闭。
2. 线程工厂(ThreadFactory)
线程工厂用于创建新线程,通过ThreadFactory接口定义。它使得线程的创建过程可以定制化,例如设置线程名称、优先级、是否为守护线程等。使用自定义线程工厂可以更好地监控和管理线程。
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class CustomThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
CustomThreadFactory(String threadNamePrefix) {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
namePrefix = threadNamePrefix + "-" + poolNumber.getAndIncrement() + "-thread-";
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
if (t.isDaemon())
t.setDaemon(false); // 设置为非守护线程
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY); // 设置优先级为正常
return t;
}
}
3. 拒绝策略及自定义实现
Java线程池提供了四种预设的拒绝策略:
- AbortPolicy(抛出异常)
- CallerRunsPolicy(调用者线程执行任务)
- DiscardPolicy(静默丢弃任务)
- DiscardOldestPolicy(丢弃队列中最旧的任务)
自定义拒绝策略示例:
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
public class CustomRejectPolicy implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.err.println("自定义拒绝策略: 任务被拒绝,任务=" + r.toString());
// 可以添加日志记录、报警、备用处理逻辑等
}
}
4. 判断线程池中的任务是否执行完成
使用awaitTermination()方法来判断线程池中的所有任务是否执行完成。通常在调用shutdown()后使用。
executor.shutdown();
try {
if (executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)) {
System.out.println("所有任务执行完毕");
} else {
System.out.println("线程池未正常关闭");
}
} catch (InterruptedException e) {
executor.shutdownNow(); // 中断并尝试停止所有任务
Thread.currentThread().interrupt(); // 重置中断状态
}
整合示例
将上述概念整合在一个简单的线程池使用示例中:
import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) {
// 线程工厂实例
ThreadFactory factory = new CustomThreadFactory("MyThreadPool");
// 自定义拒绝策略实例
RejectedExecutionHandler customRejectHandler = new CustomRejectPolicy();
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
8, // 核心线程数
16, // 最大线程数
60, // 空闲线程存活时间
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100), // 任务队列
factory, // 线程工厂
customRejectHandler // 拒绝策略
);
// 提交任务
for (int i = 0; i < 20; i++) {
int taskId = i;
executor.execute(() -> {
System.out.println("执行任务:" + taskId + ", 执行线程:" + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
// 关闭线程池
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
if (!executor.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("线程池未正常关闭");
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
此示例展示了如何创建一个具备自定义线程工厂和拒绝策略的线程池,并提交任务,最后正确关闭线程池。