1. 线程池的继承关系
从上图可以看出来最顶层的接口为 Executor
,下面看一下这个接口中的方法
public interface Executor {
//只有一个方法execute
void execute(Runnable command);
}
从代码中可以看出来只有一个 execute
方法。这也是我常用的一个来运行 Runable
的一种方式。然后看一下继承了 Executor
接口的 ExecutorService
接口中有哪些我们熟悉的而常用的方法
public interface ExecutorService extends Executor {
// 关闭线程池,已提交的任务继续执行,不接受继续提交新任务
//写例子的时候用到(PS在实际的项目组基本上没有用到,反正我是没有)
void shutdown();
//关闭线程池,尝试停止正在执行的所有任务,不接受继续提交新任务
//这个也是基本上没用到
List<Runnable> shutdownNow();
// 线程池是否已关闭
// 还是没有用到
boolean isShutdown();
// 这个方法必须在调用shutdown或shutdownNow方法之后调用才会返回true
//尴尬没用过
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);
//带返回值---(成功返回值为null 有兴趣的可以去尝试一下,源码的英文注释上面有说明)
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;
}
演示代码:
public class InvokeAllTest {
public static void main(String[] args) throws Exception{
ExecutorService service = Executors.newFixedThreadPool(10);
Collection<Test> a = new ArrayList<>();
for(int i = 0; i < 10; ++i){
a.add(new Test());
}
//System.out.println( service.invokeAny(a));
System.out.println( service.invokeAll(a));
}
}
class Test implements Callable<String>{
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
@Override
public String call() throws Exception {
TimeUnit.SECONDS.sleep((int)(Math.random()*10));
return Thread.currentThread().getName();
}
}
看一下最后一个接口 ScheduledExecutorService
计划执行接口,从命名上就不难看出来这个用于执行任务的。
public interface ScheduledExecutorService extends ExecutorService {
/**
* 创建并执行在给定延迟之后启用的一次性操作。
*/
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
/**
* 创建并执行在给定延迟之后启用的一次性操作。返回ScheduledFuture<V>
*/
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
/**
* 按指定频率周期执行某个任务。
*/
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
/**
* 按指定频率间隔执行某个任务。
*/
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
}
另外,由于线程池支持获取线程执行的结果,所以,引入了 Future 接口,RunnableFuture 继承自此接口,然后我们最需要关心的就是它的实现类 FutureTask。到这里,记住这个概念,在线程池的使用过程中,我们是往线程池提交任务(task),使用过线程池的都知道,我们提交的每个任务是实现了 Runnable 接口的,其实就是先将 Runnable 的任务包装成 FutureTask,然后再提交到线程池。这样,读者才能比较容易记住 FutureTask 这个类名:它首先是一个任务(Task),然后具有 Future 接口的语义,即可以在将来(Future)得到执行的结果。
2. AbstractExecutorService
接着来看一下在抽象类 AbstractExecutorService
实现了哪些方法
public abstract class AbstractExecutorService implements ExecutorService {
/**
* Runnable 转换为 Callable 的方法带指定返回值
*/
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
/**
* Runnable 转换为 Callable 的方法,不带指定返回值
*/
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
/**
*
*/
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
//这里看一看出来在Runnable submit方法返回值为Future get的值为null
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();
//这里看一看出来在Runnable submit方法返回值为Future get的值为result
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
/**
* Callable类型
*/
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}