Java提供了一个Executors类来帮助创建线程池,但是如果想要创建一个优雅的线程池,需要考虑以下几个方面:
- 池大小
线程池的大小需要根据任务的类型和运行环境来确定。通常,线程池的大小应该设置为处理器的数量加上1或2。
- 线程池的类型
Java提供了几种线程池类型,每种类型都有不同的特点,例如Executors.newFixedThreadPool()用于创建指定大小的线程池,Executors.newCachedThreadPool()用于创建自动调整大小的线程池。选择合适的线程池类型可以提高效率和性能。
- 任务队列
线程池中的任务队列应该能够处理线程池大小以外的任务,因此需要选择适当的队列类型(例如LinkedBlockingQueue或PriorityBlockingQueue)。
- 线程池的生命周期
线程池的生命周期可以通过实现ThreadFactory接口来控制。ThreadFactory可以定制线程的属性(例如线程名称、线程是否为后台线程等),也可以在线程创建和销毁时执行一些处理。
基于上述要点,可以编写以下优雅的线程池:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.LinkedBlockingQueue;
public class MyThreadPool {
private ExecutorService executorService;
public MyThreadPool(int poolSize) {
ThreadFactory threadFactory = new ThreadFactory() {
private int threadCount = 0;
public Thread newThread(Runnable r) {
threadCount++;
Thread t = new Thread(r, "MyThreadPool-" + threadCount);
t.setDaemon(true);
return t;
}
};
this.executorService = Executors.newFixedThreadPool(poolSize, threadFactory);
}
public void submitTask(Runnable task) {
executorService.submit(task);
}
public void shutdown() {
try {
executorService.shutdown();
executorService.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
System.out.println("MyThreadPool shutdown interrupted: " + e.getMessage());
} finally {
executorService.shutdownNow();
}
}
}
在这个例子中,创建了一个固定大小的线程池,每个线程都是一个后台线程,并且使用了ThreadFactory在线程创建和销毁时执行一些处理(即设定线程名称)。在线程池关闭时,使用了awaitTermination来等待正在执行的任务完成,并且使用shutdownNow来强制停止线程池。