Java线程池
线程池介绍
线程池的构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
参数介绍
corePoolSize(线程池基本大小):当向线程池提交任务时,如果线程池中现有的线程数小于corePoolSize,即便此时由空闲线程,也会通过创建一个新的线程来执行该任务,直到当前线程数大于等于corePoolSize。
maximumPoolSize(线程池最大线程数):当线程阻塞队列满了,且创建的线程数小于maximumPoolSize,则线程池会创建新的线程来执行任务。
keepAliveTime(线程存活时间):当非核心线程空闲时间超过了keepAliveTime,那么这个线程就会被销毁。直到线程池中的线程数等于核心线程数。unit是时间单位。
workQueue(任务队列):用于传输和保存等待执行任务的阻塞队列。
threadFactory(线程工厂):用于创建新线程,对创建的线程名可使用统一命名标准。
handler(线程饱和策略):当线程池和队列都满了,新加入的线程会执行该策略。
线程池流程

submit和execute方法
在Java的线程池编程中,submit和execute是两种提交任务的方法,它们有一些关键的区别。
方法的来源:
-
execute方法定义在Executor接口中,是线程池的基础方法,用于执行Runnable任务。
-
submit方法则定义在ExecutorService接口中,提供了更多的灵活性,可以提交实现了Callable或Runnable接口的任务。
接收的参数:
-
execute只能接收Runnable类型的参数。
-
submit可以接收Runnable和Callable两种类型的参数,这使得submit可以处理有返回值的任务。
返回值:
-
execute方法没有返回值。
-
submit方法返回一个Future对象,可以通过这个对象获取任务执行的结果。如果提交的是Runnable任务,Future.get()将返回null,因为Runnable任务本身不返回值。
异常处理:
-
使用execute提交的任务,如果在run()方法中出现异常,会直接在控制台打印异常信息。
-
使用submit提交的任务,如果在run()或call()方法中出现异常,异常信息不会立即打印。只有在调用Future.get()方法时,才会抛出异常。因此,当使用submit时,建议显式地捕获和处理异常,以避免丢失异常信息。
/**
* 该方法接收Runnable任务,没有返回值
*/
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
/**
* 会将线程执行结果赋值给result
*/
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
/**
* 返回线程执行结果
*/
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
创建线程池的静态类 Executors
Executors类提供了4种不同的线程池
newCachedThreadPool:用来创建一个可以无限扩大的线程池,适用于负载较轻的场景,多用来执行短期异步任务,不会造成cpu过度切换。
newFixedThreadPool:创建一个固定大小的线程池,采用无界的阻塞队列,所以线程数量永远不会变化,Integer.MAX_VALUE大小。适用于负载较重的场景,对当前线程数量进行限制。(保证线程数可控,不会造成线程过多,导致系统负载更为严重)
newSingleThreadExecutor:创建一个单线程的线程池,适用于需要保证顺序执行各个任务。与自己创建一个线程的区别:自己创建的线程抛出异常后,线程不会恢复,线程池的线程在异常后,会自动创建一个新的线程。
newScheduledThreadPool:适用于执行延时或者周期性任务。