您的位置:首页 > 编程语言 > Java开发

【Java并发】- ScheduledThreadPoolExecutor, ScheduledExecutorService使用

2017-07-03 10:06 417 查看

概述

ScheduledExecutorService可以在给定的延迟后运行或者定期的执行任务。
ScheduledThreadPoolExecutor继承自ThreadPoolExecutor同时实现了ScheduledExecutorService接口,在ThreadPoolExecutor的基础上支持执行延迟任务或者周期性的任务。

ScheduledExecutorService接口

ScheduledExecutorService的接口集成关系:

Executor
      |---ExecutorService
                 |--ScheduledExecutorService

ScheduledExecutorService除了父接口定义的方法之外同时新增了四个方法

ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);   创建并执行在给定延迟后启用的 命令。
ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);  创建并执行给定延迟后执行的命令,可以有返回值。
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay,  long period, TimeUnit unit);  创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;也就是将在initialDelay后开始执行,然后在initialDelay+period 后执行,接着在initialDelay + 2
* period 后执行,依此类推。
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit); 创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。

scheduleAtFixedRate和[b]scheduleWithFixedDelay的区别:[/b]

scheduleAtFixedRate的执行流程:1)创建任务后经过initialDelay时间后任务开始执行。 2)执行任务(会执行一定的时间假设为workTime)。 3)如果workTime小于period那么下一次任务将在延迟period - workTime之后执行。 4)如果workTime大于period那么下一次任务将在上一次任务完成之后立刻执行。

scheduleWithFixedDelay的执行流程: 1)创建任务后经过initialDelay时间后任务开始执行。 2)执行任务。 3)延迟delay时间之后执行下一次任务。


[b]注意:[/b]

对于shceduleAtFixedRate即使设置了period,并不意味着每次任务开始的时间间隔一定是period。
对于shceduleAtFixedRate如果执行任务时间大于period,线程池并不会去尝试并发的执行下一次任务,而是去等待任务的完成。
对于scheduleWithFixedDelay则定义的是一次任务的结束和下一次任务的开始之间的时间间隔。
initialDelay可以为0或者负数,代表立刻执行。而period和delay参数不能为小于等于0的数。

ScheduledThreadPoolExecutor使用

schedule

下面的示例将在延迟2秒后执行
public static void main(String[] args) {

final long startNanoTime = System.nanoTime();

ScheduledThreadPoolExecutor scheduledThreadPool = new ScheduledThreadPoolExecutor(3);
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("run after " + (System.nanoTime() - startNanoTime) + " nanoseconds");
}
}, 2000, TimeUnit.MILLISECONDS);

scheduledThreadPool.shutdown();
}


输出:
run after 2012715739 nanoseconds


使用Callable:
下面的例子中任务将在2秒后执行,并获取结果
public static void main(String[] args) throws InterruptedException, ExecutionException {

final long startNanoTime = System.nanoTime();

ScheduledThreadPoolExecutor scheduledThreadPool = new ScheduledThreadPoolExecutor(3);
ScheduledFuture<String> future = scheduledThreadPool.schedule(new Callable<String>() {
@Override
public String call() {
System.out.println("run after " + (System.nanoTime() - startNanoTime) + " nanoseconds");
return "hello";
}
}, 2000, TimeUnit.MILLISECONDS);

scheduledThreadPool.shutdown();
String result = future.get();
System.out.println("result:" + result);
}
输出:
run after 2019487011 nanoseconds
result:hello

scheduleAtFixedRate

下面的例子将在延迟1秒后开始周期性的执行任务,period为3秒,同时每个任务的执行时间大约1秒,并在10秒后线程池不再接受新的任务(也就是不能开始下一个任务)。

public static void main(String[] args) throws InterruptedException {

final long startNanoTime = System.nanoTime();

ScheduledThreadPoolExecutor scheduledThreadPool = new ScheduledThreadPoolExecutor(3);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("start after " + (System.nanoTime() - startNanoTime) + " nanoseconds");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end after " + (System.nanoTime() - startNanoTime) + " nanoseconds");
}
}, 1000, 3000, TimeUnit.MILLISECONDS);

Thread.sleep(10000);
scheduledThreadPool.shutdown();
}


输出:
start after 1019976362 nanoseconds
end after 2019330599 nanoseconds
start after 4019771918 nanoseconds
end after 5029644740 nanoseconds
start after 7019470590 nanoseconds
end after 8019744413 nanoseconds


当执行任务的时间大于period的情况:
任务的执行时间为1秒到4秒之间的随机数,而period为2000
public static void main(String[] args) throws InterruptedException {

final long startNanoTime = System.nanoTime();

ScheduledThreadPoolExecutor scheduledThreadPool = new ScheduledThreadPoolExecutor(3);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("start after " + (System.nanoTime() - startNanoTime) + " nanoseconds");
try {
//random 1000 ~ 4000
long workTime = (new Random().nextInt(3) + 1) * 1000;
Thread.sleep(workTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end after " + (System.nanoTime() - startNanoTime) + " nanoseconds");
}
}, 1000, 2000, TimeUnit.MILLISECONDS);

Thread.sleep(10000);
scheduledThreadPool.shutdown();
}


输出:
start after 1006115247 nanoseconds
end after 3008216336 nanoseconds
start after 3009197502 nanoseconds
end after 6011075674 nanoseconds
start after 6011498519 nanoseconds
end after 7012644717 nanoseconds
start after 7013034720 nanoseconds
end after 10021524058 nanoseconds


可以看到第二次任务执行的时候耗时大约3秒,而下一次任务的执行是等到上次执行完了之后立马就开始。

scheduleWithFixedDelay

下面的程序任务的结束和下一次任务的开始总是间隔2秒
public static void main(String[] args) throws InterruptedException {

final long startNanoTime = System.nanoTime();

ScheduledThreadPoolExecutor scheduledThreadPool = new ScheduledThreadPoolExecutor(3);
scheduledThreadPool.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println("start after " + (System.nanoTime() - startNanoTime) + " nanoseconds");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end after " + (System.nanoTime() - startNanoTime) + " nanoseconds");
}
}, 1000, 2000, TimeUnit.MILLISECONDS);

Thread.sleep(10000);
scheduledThreadPool.shutdown();
}


输出:
start after 1009844085 nanoseconds
end after 2012320399 nanoseconds
start after 4014939576 nanoseconds
end after 5030251092 nanoseconds
start after 7045771978 nanoseconds
end after 8055412441 nanoseconds

注意:在调用了shutdown方法之后,线程池将不再接收任何任务,包括正在延时准备执行的任务。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: