public interface Executor{
void execute(Runnable cmd);
}
如此简单的接口,却为一个灵活而强大的框架创造了基础。使得线程的执行逻辑和时序逻辑得到了分离,提高了健壮性和可扩张性,使得需求变化时不再是将整个程序重写而只需修改相应的执行逻辑
Executor解藕了任务的执行策略和任务的执行过程: 只要提交给Executor一个Runnable,Exector根据自身的执行策略(如使用线程池,定时执行,或单线程等等),去调用runnable的run方法。Executor只是指定执行的策略,只知道Runnable有个run方法,不需要知道run what;而 Runnable只需要知道自己到底做什么,不需要知道到底按什么顺序做,什么时刻做。
这里面有两个变化点:“做什么” 和 ”怎么做“的变化 。当系统有多个变化点时,我们一般的做法是对每个变化点分别进行封装 。这样使得每个对象(类)只需要管理一种变化。一个变化了,不会影响到其他的变化点,保证了可扩展性。
Executor实际上就是一个Command模式。命令模式使用很常见,GUI的Swing中菜单命令,JDBC的Query命令对象等等(这里不说Command模式了,想写的时候在写吧)。
类库中提供了几个Executor的实现(主要用于线程池),通过调用Executors的某个静态方法来创建:
newFixedThreadPool 创建一个顶长的线程池。
newCacheThreadPoo; 创建一个可缓存的线程池。如果当前线程池的长度超过了处理的需要,就回收空闲线程;当需求增加是,灵活增加新的线程。
newSingleThreadExecutor 创建一个单线程的executor
newScheduleThreadPool 创建一个定长的线程池,支持定时的以及周期性的执行(替代Timer)
new Thread(runnable).start()
并且可能最终希望获得一个更加灵活的执行策略是,考虑使用Executor代替Thread
ExecutorService继承了Executor,提供了对生命周期管理。
public interface ExecutorService exetends Executor {
void shutdown(();
List<Runnable> shutdownNow();
boolean isShutdown();
boolean istermindated();
boolean awaitTermination(long timeout, TimeUnit unit)
throw InterruptedException;
//....其他用于任务提交的便利方法
}