@adamhand
2018-12-23T22:05:04.000000Z
字数 5366
阅读 1127
public interface Executor {
void execute(Runnable command);
}
Executor接口是Executor框架中最基础的部分,定义了一个用于执行Runnable的execute方法,它没有实现类只有另一个重要的子接口ExecutorService
//继承自Executor接口
public interface ExecutorService extends Executor {
/**
* 关闭方法,调用后执行之前提交的任务,不再接受新的任务
*/
void shutdown();
/**
* 从语义上可以看出是立即停止的意思,将暂停所有等待处理的任务并返回这些任务的列表
*/
List<Runnable> shutdownNow();
/**
* 判断执行器是否已经关闭
*/
boolean isShutdown();
/**
* 关闭后所有任务是否都已完成
*/
boolean isTerminated();
/**
* 中断
*/
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
/**
* 提交一个Callable任务
*/
<T> Future<T> submit(Callable<T> task);
/**
* 提交一个Runable任务,result要返回的结果
*/
<T> Future<T> submit(Runnable task, T result);
/**
* 提交一个任务
*/
Future<?> submit(Runnable task);
/**
* 执行所有给定的任务,当所有任务完成,返回保持任务状态和结果的Future列表
*/
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
/**
* 执行给定的任务,当所有任务完成或超时期满时(无论哪个首先发生),返回保持任务状态和结果的 Future 列表。
*/
<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接口,定义了终止、提交、执行任务、跟踪任务返回结果等方法。
ExecutorService的生命周期有三种状态:运行、关闭和已终止。
负责生成各种类型的ExecutorService线程池实例,共有四种。
// 实现Runnable接口的类将被Thread执行,表示一个基本的任务
public interface Runnable {
// run方法就是它所有的内容,就是实际执行的任务
public abstract void run();
}
与Runnable接口的区别在于它接收泛型,同时它执行任务后带有返回内容
// Callable同样是任务,与Runnable接口的区别在于它接收泛型,同时它执行任务后带有返回内容
public interface Callable<V> {
// 相对于run方法的带有返回值的call方法
V call() throws Exception;
}
Runnable接口和Callable接口的实现类,都可以被ThreadPoolExecutor和ScheduledThreadPoolExecutor执行,他们之间的区别是Runnable不会返回结果,而Callable可以返回结果。
Executors可以把一个Runnable对象转换成Callable对象:
public static Callable<Object> callable(Runnbale task);
当把一个Callable对象(Callable1,Callable2)提交给ThreadPoolExecutor和ScheduledThreadPoolExecutor执行时,submit(...)会向我们返回一个FutureTask对象。我们执行FutureTask.get()来等待任务执行完成,当任务完成后,FutureTask.get()将返回任务的结果。
// Future代表异步任务的执行结果
public interface Future<V> {
/**
* 尝试取消一个任务,如果这个任务不能被取消(通常是因为已经执行完了),返回false,否则返回true。
*/
boolean cancel(boolean mayInterruptIfRunning);
/**
* 返回代表的任务是否在完成之前被取消了
*/
boolean isCancelled();
/**
* 如果任务已经完成,返回true
*/
boolean isDone();
/**
* 获取异步任务的执行结果(如果任务没执行完将等待)
*/
V get() throws InterruptedException, ExecutionException;
/**
* 获取异步任务的执行结果(有最常等待时间的限制)
*
* timeout表示等待的时间,unit是它时间单位
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果
也就是说Future提供了三种功能:
线程池优先要创建出基本线程池大小(corePoolSize)的线程数量,没有达到这个数量时,每次提交新任务都会直接创建一个新线程,当达到了基本线程数量后,又有新任务到达,优先放入等待队列,如果队列满了,才去创建新的线程(不能超过线程池的最大数maxmumPoolSize)。
ExecutorService threadpool= Executors.newFixedThreadPool(10);
threadpool.execute(new Runnable(){...});
这种方式提交没有返回值,也就不能判断任务是否被线程池执行成功。
Future<?> future = threadpool.submit(new Runnable(){...});
try {
Object res = future.get();//获取任务执行结果
} catch (InterruptedException e) {
// 处理中断异常
e.printStackTrace();
} catch (ExecutionException e) {
// 处理无法执行任务异常
e.printStackTrace();
}finally{
// 关闭线程池
executor.shutdown();
}
使用submit 方法来提交任务,它会返回一个Future对象,通过future的get方法来获取返回值,get方法会阻塞住直到任务完成,而使用get(long timeout, TimeUnit unit)方法则会阻塞一段时间后立即返回,这时有可能任务没有执行完。
volatile int runState;
static final int RUNNING = 0; //运行状态
static final int SHUTDOWN = 1; //关闭状态
static final int STOP = 2; //停止
static final int TERMINATED = 3; //终止,终结
ForkJoinPool是jdk1.7新引入的线程池,基于ForkJoin框架,使用了“分治”的思想。关于ForkJoin框架参考另一篇笔记“Java并发之J.U.C”。
ThreadPoolExecutor中每个任务都是由单个线程独立处理的,如果出现一个非常耗时的大任务(比如大数组排序),就可能出现线程池中只有一个线程在处理这个大任务,而其他线程却空闲着,这会导致CPU负载不均衡:空闲的处理器无法帮助工作繁忙的处理器。
ForkJoinPool就是用来解决这种问题的:将一个大任务拆分成多个小任务后,使用fork可以将小任务分发给其他线程同时处理,使用join可以将多个线程处理的结果进行汇总;这实际上就是分治思想的并行版本。
ForkJoinPool 类是Fork/Join 框架的核心,和ThreadPoolExecutor一样它也是ExecutorService接口的实现类。
所以上面的线程池框架图是比较老的了,新的框架图如下图所示:
(未完待续)
https://www.jianshu.com/p/32a15ef2f1bf
https://www.jianshu.com/p/de025df55363
https://blog.csdn.net/Holmofy/article/details/82714665
https://www.cnblogs.com/lixuwu/p/7979480.html