一、ScheduledExecutorService是一个接口,是继承于接口ExecutorService的子类,而ExecutorService又是继承于Executor接口的子类。
二、这里我们先从继承的最终类Executor接说起。
Executor接口只有一个方法:void execute(Runnable command);他是一个同步方法,接收一个Runnable接口作为参数。具体由implements实现他的类来实现。
execute():一个同步方法;与之对应的是一步方法enqueue()。二者区别:
execute():同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回,处于等待状态直到得到该调用的结果。
也就是必须一件一件事做,等前一件做完了才能做下一件事.
enqueue():异步,当一个异步过程调用发出后,他可以做其他的任务处理,不必等待调用结果。实际处理这个调用的部件在
完成后,通过状态、通知和回调来通知调用者。简单说就是调用者可以同时处理很多事情,而不是一件接一件。
因此,Executor接口理解起来很简单,不用多说。
三、接下来我们继续说接口ExecutorService。这个接口稍微复杂一点。它包含一下四大系列的方法:
1、shutdown系列方法:
void shutdown();作用:平滑的关闭ExecutorService,当此方法被调用时,ExecutorService停止接收新的任务并且等待已经提交的任务(包含提交正在执行和提交未执行)执行完成。当所有提交任务执行完毕,线程池即被关闭。
List<Runnable> shutdownNow();作用:获取终止线程池中线程的执行的时候线程池中线程列表。
boolean isShutdown();作用:判断线程是否已经停止执行
2、Terminate系列方法:
boolean isTerminated();作用:确认线程是否已经停止执行
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;作用::接收人timeout和TimeUnit两个参数,用于设定超时时间及单位。当等待超过设定时间时,会监测ExecutorService是否已经关闭,若关闭则返回true,否则返回false。一般情况下会和shutdown方法组合使用。
简单来说就是:shutdown()用于关闭线程池,awaitTermination()用于确定线程池是否已经关闭。具体使用如下:
public class Task implements Callable{
@Override
public Object call() throws Exception {
System.out.println("普通任务");
return null;
}
}
public class LongTask implements Callable{
@Override
public Object call() throws Exception {
System.out.println("长时间任务");
TimeUnit.SECONDS.sleep(5);
return null;
}
}
public class TestShutDown {
public static void main(String[] args) throws InterruptedException{
ScheduledExecutorService service = Executors.newScheduledThreadPool(4);
service.submit(new Task());
service.submit(new LongTask());
service.submit(new Task());
// 平滑的关闭ExecutorService
service.shutdown();
// 在1秒钟后监测ExecutorService是否已经关闭
while (service.isShutdown() || service.isTerminated() || !service.awaitTermination(1, TimeUnit.SECONDS)){
System.out.println("线程池没有关闭");
}
System.out.println("线程池已经关闭");
}
}
3、submit()系列方法:
submit(Callable<T> task);作用:接收一个实现了Callable接口的参数,使用方式如上面main()方法中。
submit(Runnable task, T result);作用:接收一个实现了Runnable 接口的参数以及一个泛型参数T,泛型参数可以为null,这时跟下面的这个方法相同。
submit(Runnable task);作用:接收一个实现了Runnable 接口的参;
submit()方法接收一个实现了Runnable 接口的参数的使用如下:
ScheduledExecutorService executorService04 = new ScheduledThreadPoolExecutor(3);
executorService04.submit(new Runnable() {
@Override
public void run() {
// TODO:
}
});
或者:
executorService04.submit(new Runnable() {
@Override
public void run() {
// TODO:
}
}, null);
此二者的使用没什么大的不同,另外,从实现的功能上来看,他与前面的submit(Callable task)接收一个实现了Callable接口的参数方法一样,不同的用法而已。
4、invoke系列方法:
<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;
上面这四个方法没有深入的研究和使用过,不知道其具体的作用,但从其命名( invoke:调用)来看,不难理解:
调用所有或者任意一个实现了Callable接口为对象的Collection集合为参数的方法。若有timeout参数,则是监控其运行超时。
invoke系列方法先就讲这么多,以后研究透了再来细说。
四、终于轮到ScheduledExecutorService了,他有4个方法:
// schedule方法调度的任务在delay时长的延迟后只执行一次。
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);
//根据前面的代码解说,我们可以推测:他其实和上面的schedule()方法一样
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);
// scheduleAtFixedRate:该方法在initialDelay时长后第一次执行任务,以后每隔period时长,再次执行任务。注意,period是从任务开始执行算起的。开始执行任务后,定时器每隔period时长检查该任务是否完成,如果完成则再次启动任务,否则等该任务结束后才再次启动任务。
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
// 该方法在initialDelay时长后第一次执行任务,以后每当任务执行完成后,等待delay时长,再次执行任务。
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);
贴上使用代码及运行结果:
ScheduledExecutorService executorService00;
ScheduledExecutorService executorService01;
ScheduledExecutorService executorService02;
ScheduledExecutorService executorService03;
ScheduledExecutorService executorService04;
ScheduledExecutorService executorService05;
ScheduledExecutorService executorService06;
private void scheduledTimer() throws InterruptedException {
executorService00 = new ScheduledThreadPoolExecutor(2);
executorService00.schedule(new Callable<Object>() {
@Override
public Object call() throws Exception {
Log.i(TAG, "ScheduledExecutorService00 \n ScheduledThreadPoolExecutor的schedule方法接收一个Callable对象作为参数");
return null;
}
}, 1, TimeUnit.SECONDS);
executorService01 = new ScheduledThreadPoolExecutor(2);
// schedule方法调度的任务在delay时长的延迟后只执行一次。
executorService01.schedule(runnable01, 3, TimeUnit.SECONDS);
executorService02 = new ScheduledThreadPoolExecutor(2);
// scheduleAtFixedRate:该方法在initialDelay时长后第一次执行任务,以后每隔period时长,再次执行任务。
// 注意,period是从任务开始执行算起的。开始执行任务后,定时器每隔period时长检查该任务是否完成,
// 如果完成则再次启动任务,否则等该任务结束后才再次启动任务。
executorService02.scheduleAtFixedRate(runnable02, 2, 2, TimeUnit.SECONDS);
executorService03 = new ScheduledThreadPoolExecutor(2);
// 该方法在initialDelay时长后第一次执行任务,以后每当任务执行完成后,等待delay时长,再次执行任务。
executorService03.scheduleWithFixedDelay(runnable03, 1, 1, TimeUnit.SECONDS);
executorService04 = new ScheduledThreadPoolExecutor(2);
executorService04.execute(runnable04);
executorService05 = new ScheduledThreadPoolExecutor(3);
executorService05.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
Log.i(TAG, "ScheduledExecutorService05 \n ScheduledThreadPoolExecutor实现了ScheduledExecutorService接口," +
"继承于ThreadPoolExecutor");
return null;
}
});
executorService06 = new ScheduledThreadPoolExecutor(3);
executorService06.submit(new Runnable() {
@Override
public void run() {
Log.i(TAG, "ScheduledExecutorrunnable06 \n ScheduledThreadPoolExecutor实现了ScheduledExecutorService接口," +
"继承于ThreadPoolExecutor");
}
});
executorService03.shutdown();
Log.i(TAG, "ScheduledExecutorscheduledTimer: isShutdown===" + executorService03.isShutdown());
Log.i(TAG, "ScheduledExecutorTimer: isTerminated===" + executorService03.isTerminated());
boolean awaitTermination = executorService03.awaitTermination(5, TimeUnit.SECONDS);
Log.i(TAG, "ScheduledExecutorscheduledTimer: awaitTermination===" + awaitTermination);
if (awaitTermination){
Log.i(TAG, "ScheduledExecutorscheduledTimer: 线程池没有关闭===");
}
}
Runnable runnable01 = new Runnable() {
@Override
public void run() {
Log.i(TAG, "ScheduledExecutorrunnable01 \n ScheduledThreadPoolExecutor的schedule方法接收一个Runnable对象作为参数");
}
};
Runnable runnable02 = new Runnable() {
@Override
public void run() {
Log.i(TAG, "ScheduledExecutorrunnable02 \n ScheduledThreadPoolExecutor的schedule方法接收一个Runnable对象作为参数");
}
};
Runnable runnable03 = new Runnable() {
@Override
public void run() {
Log.i(TAG, "ScheduledExecutorrunnable03 \n ScheduledThreadPoolExecutor的schedule方法接收一个Runnable对象作为参数");
}
};
Runnable runnable04 = new Runnable() {
@Override
public void run() {
Log.i(TAG, "ScheduledExecutorrunnable04 \n ScheduledThreadPoolExecutor的schedule方法接收一个Runnable对象作为参数");
}
};
运行结果如下:
好了,ScheduledExecutorService学习讲解完毕,下一篇,我们学习分析ScheduledThreadPoolExecutor