线程池是并发编程中的一个重要工具,可以有效地管理和调度线程。Java 提供了丰富的线程池实现和配置选项。
1. 线程池的三大方法
- execute(Runnable command):
执行一个没有返回值的任务。适用于不需要返回结果的任务。- submit(Callable<T> task) 或 submit(Runnable task, T result):
执行一个有返回值的任务,可以提交Callable
或Runnable
,并返回一个Future
对象,用于获取任务的执行结果。- invokeAll(Collection<? extends Callable<T>> tasks):
执行一批任务,返回一批Future
对象。所有任务执行完毕后,调用者可以获取每个任务的结果。
ExecutorService executor = Executors.newFixedThreadPool(2);
// execute
executor.execute(() -> System.out.println("Task executed"));
// submit
Future<String> future = executor.submit(() -> "Task result");
List<Callable<String>> tasks = Arrays.asList(
() -> "Task 1 result",
() -> "Task 2 result"
);
// invokeAll
List<Future<String>> futures = executor.invokeAll(tasks);
executor.shutdown();
2. 线程池的七大参数
创建线程池时,可以通过 ThreadPoolExecutor
类的构造函数指定以下七个参数:
corePoolSize:
核心线程池大小,线程池在没有任务执行时也会维护这些线程。maximumPoolSize:
最大线程池大小,线程池能够容纳的最大线程数keepAliveTime:
非核心线程的空闲存活时间。当线程池中线程数量超过核心线程数量时,多余的线程在空闲时间超过keepAliveTime
时会被销毁。unit:
keepAliveTime
的时间单位。workQueue:
任务队列,用于存储等待执行的任务threadFactory:
线程工厂,用于创建新线程。handler:
拒绝策略,当任务太多来不及处理时如何处理新任务。
ExecutorService executor = new ThreadPoolExecutor(
2, // corePoolSize
4, // maximumPoolSize
60, // keepAliveTime
TimeUnit.SECONDS, // unit
new LinkedBlockingQueue<>(10), // workQueue
Executors.defaultThreadFactory(),// threadFactory
new ThreadPoolExecutor.AbortPolicy() // handler
);
3. 线程池的四种拒绝策略
AbortPolicy(默认策略):抛出
RejectedExecutionException
,阻止系统正常工作CallerRunsPolicy:由调用线程处理该任务。这种策略不会抛弃任务或抛出异常,但会阻塞提交任务的线程,直到可以提交任务
DiscardPolicy:直接丢弃任务,不予处理,不抛出异常
DiscardOldestPolicy:丢弃队列中最老的一个任务,并尝试重新提交当前任务
4. Executors 类
Java 的 Executors
工具类提供了几种方便的创建线程池的方法,这些方法封装了常用的 ThreadPoolExecutor
配置,简化了线程池的使用。以下是 Executors
创建线程池的几种方法:
1. newFixedThreadPool(int nThreads)
创建一个固定大小的线程池,线程池中的线程数量固定。
如果所有线程都在执行任务,新提交的任务会在队列中等待。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
2. newCachedThreadPool()
创建一个可缓存的线程池。如果线程池中有空闲线程可以重用,则会重用这些线程;
如果所有线程都在执行任务,则会创建新的线程。空闲线程会在60秒后被终止和移除。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
3. newSingleThreadExecutor()
创建一个单线程的线程池。
它确保所有任务在同一个线程中按顺序执行,适用于需要按顺序执行任务的场景。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
4. newScheduledThreadPool(int corePoolSize)
创建一个支持定时及周期性任务执行的线程池。
适用于需要定期执行任务的场景。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
通过灵活地配置线程池的参数和拒绝策略,可以在不同的应用场景下实现高效的任务调度和资源管理。