在Executor执行框架源代码分析(一)中已经介绍过ThreadFactory和Executor的作用和关系。本文继续讨论ThreadFactory和Executor的具体实现。
一、ThreadFactory
ThreadFactory的目的是为了让用户可以创建定制化的线程。所以,除了一个DefaultThreadFactory之外,这个接口在JDK中基本没有具体的实现,主要还是用户自己进行定制。这里我们看一下 DefaultThreadFactory的实现,了解一下ThreadFactory的具体使用方式即可。DefaultThreadFactory的源代码如下:
static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +poolNumber.getAndIncrement() +"-thread-";
}
public Thread newThread(Runnable r) {
//使用group和namePrefix创建线程
Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(),0);
//如果创建的是守护线程,则修改为普通线程,也就是说这里只创建普通线程
if (t.isDaemon())
t.setDaemon(false);
//设置线程的优先级为5,如果不是5 ,则修改为5
//说明DefaultThreadFactory创建的线程,其优先级都是5
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
从上面的代码中可以看到,DefaultThreadFactory创建的线程带有特定的name , group,优先级为5,且都是普通线程。这就是ThreadFactory的定制的目的,用户可以根据自己的需要创建定制化的线程。
二、Executor
Executor还有一个子接口——ExecutorService,ExecutorService扩展了Executor,提供了更多的任务执行方法。方法如下:
void shutdown();
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)
<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)
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
<T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
这些方法主要分为两类:第一,运行方法(submit和invoke*);第二,关闭方法(shutdown和awaitTernination);
各个方法的功能:
1、submit 、invokeAll和invokeAny
ExecutorService提供了执行任务(task)的服务,那么就会有各种各样的task被传递到ExecutorService,这个传递的过程被称之为提交(submit)或者执行(executor)。所以submit方法的意图很明显,就是将task提交给ExecutorService, 由ExecutorService进行执行。submit、invokeAll和invokeAny方法都能够将task提交给ExecutorService,不同之处如下:
1)submit一次只提交一个task, 而invokeAll和invokeAny一次提交多个。
2)invokeAll会执行完成所有提交的task,而invokeAny只需要有一个task执行完成,就会取消其他task任务的执行。这里的执行完成有三层含义:第一,task正确的执行完成; 第二, task执行过程中抛出异常,也算执行完成; 第三,执行超时,抛出异常也算执行完成。
3)invokeAll和invokeAny提交的task是一个Callablele类型的,而submit既可以提交Callable类型的task,也可以提交Runnable类型的task。
注:关于Callable与Runnable,两者的定义形基本是一样的,均符合jdk8中关于函数式接口的定义。Callable接口中只有一个方法(call),而Runnable接口中也只有一个方法(run)。Callable和Runnable均代表着一个任务(a task)。两者的主要区别在于两点:第一,Callable运行之后有返回结果,而Runnable则没有;第二,是否有检查异常。Runnable的run方法是不能抛出检查异常的,而Callable的call方法本身就带有Exception,支持检查异常的抛出。
submit有两个重载的方法,submit(Runnable task, T result)和submit(Runnable task)。
submit(Runnable task, T result)的含义是:如果task正确的执行完成(正确执行,没有抛异常),则Future对象(方法的返回对象)的get()方法将会返回result (这个参数是调用方法时传进去的)。
submit(Runnable task)方法的含义是:如果task正确的执行完成(正确执行,没有抛异常),则Future对象(方法的返回对象)的get()方法将会返回null。
2、shutdwon、shutdownNow和awaitTernination
Executor的执行能力是有限的(一般是线程池提供的线程数),当超过这个限制的时候就需要让后续提交的task处于等待的状态,也就出现了等待队列。
shutdown方法:调用之后,Executor将不会再接收新的task,但是会将正在运行的task和等待队列的task执行完成。
shutdownNow方法:调用之后,Executor会在接收task,同时停止等待执行的task和正在运行的线程,返回等待队列。
awaitTernination :必须在调用shutdown或者shutdownNow方法之后调用,用于 阻塞等待所有的task执行完成。
这两个方法均是立即返回的,也就是说shutdown不会等到waiting list中的task执行完成,再返回;shutdownNow也不会等待所有的task都停止之后,再返回。因此在调用shutdown和shutdownNow方法之后,需要调用awaitTernination方法等待task执行完成。
3、isShutdown和isTerminated
isShutdown : 当Executor是shutdown或者terminated状态之后,返回true;
isTerminated : 当Executor是terminated状态之后,返回true; 这个方法必须是在shutdown和shutdownNow之后调用,否则永远返回false;