在并发量较大的情况下, 每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。
new Thread的弊端如下:
a. 每次new Thread新建对象性能差。
b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom(内存溢出)。
c. 缺乏更多功能,如定时执行、定期执行、线程中断。
相比new Thread,Java提供的线程池的好处在于:
a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。
b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
c. 提供定时执行、定期执行、单线程、并发数控制等功能。
Executor
public interface Executor {
void execute(Runnable command);
}
Executor是java线程池的核心接口,用来并发执行提交的任务,提供execute(Runnable)方法用来提交任务,返回值为void。不能取消任务,没有提供和关闭线程池有关的方法。
ExecutorService
public interface ExecutorService extends Executor {
void shutdown();
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
ExecutorService接口继承了Executor接口,提供了返回 Future 对象,终止,关闭线程池等方法。当调用 shutDown 方法时,线程池会停止接受新的任务,但会完成正在 pending 中的任务。
submit方法其实调用了Callable的call。该方法将返回一个Future接口的对象,它的泛型参数代表了call方法要返回的参数类型。
Future 对象提供了异步执行,这意味着无需等待任务执行的完成,只要提交需要执行的任务,然后在需要时检查 Future 是否已经有了结果,如果任务已经执行完成,就可以通过 Future.get() 方法获得执行结果。需要注意的是,Future.get() 方法是一个阻塞式的方法,如果调用时任务还没有完成,会等待直到任务执行结束。
首先,可以用isDone()方法来查询Future是否已经完成,任务完成后,可以调用get()方法来获取结果。如果不加判断直接调用get方法,此时如果线程未完成,get将阻塞,直至结果准备就绪。
通过 ExecutorService.submit() 方法返回的 Future 对象,还可以取消任务的执行。Future 提供了 cancel() 方法用来取消执行 pending 中的任务。
AbstractExecutorService
public abstract class AbstractExecutorService implements ExecutorService {
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
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;
}
private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks, boolean timed, long nanos)
...
}
public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
try {
return doInvokeAny(tasks, false, 0);
} catch (TimeoutException cannotHappen) {
assert false;
return null;
}
}
public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return doInvokeAny(tasks, true, unit.toNanos(timeout));
}
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
...
}
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException {
...
}
}
AbstractExecutorService是一个抽象类,它实现了ExecutorService接口。
ThreadPoolExecutor
public class ThreadPoolExecutor extends AbstractExecutorService {
...
}
ThreadPoolExecutor继承了类AbstractExecutorService。
ScheduledExecutorService
public interface ScheduledExecutorService extends ExecutorService {
...}
ScheduledExecutorService接口继承了ExecutorService接口。
ScheduledThreadPoolExecutor
public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorService {
...
}
ScheduledThreadPoolExecutor类继承了ThreadPoolExecutor,实现了ScheduledExecutorService接口。
Executors
Executors 是一个工具类,类似于 Collections。提供工厂方法来创建不同类型的线程池。public class Executors {
/**
* newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程
* 线程池为无限大,如果当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程
*/
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
/**
* newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
* 定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()
*/
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
/**
* newScheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行
* ScheduledFuture<?> ScheduledThreadPoolExecutor.schedule(Runnable command, long delay, TimeUnit unit)表示延迟delay个unit执行
* ScheduledFuture<?> ScheduledThreadPoolExecutor.scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)表示延迟initialDelay个unit后,每隔period个unit执行一个任务
* ScheduledFuture<?> ScheduledThreadPoolExecutor.scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)表示延迟initialDelay个unit后,每个任务执行完后隔period个unit执行下一个任务
*/
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
/**
* newSingleThreadExecutor创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
* @return
*/
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
}