在Java中我们如果要实现定时周期性的任务,ScheduledThreadPoolExecutor会是我们的首选,本文的工作就是了解此类的使用:
代码清单1:Task1
package org.4spaces;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.Callable;
public class Task1 implements Callable<String> {
@Override
public String call() throws Exception {
String base = "2sdfasdf2e3reasdfasdf";
Random random = new Random();
StringBuffer sb = new StringBuffer();
int num = 0;
for (int i = 0; i < 10; i++) {
num = random.nextInt(base.length());
sb.append(base.charAt(num));
}
System.out.println("Task running :" + new Date());
return sb.toString();
}
}
此类的作用是:生成10个字符字符串,使用Callable的目的是我们不在任务中直接输出结果,而主动获取任务的结果。
代码清单2:LongTask
package org.4spaces;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
public class LongTask implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("LongTask running: "+new Date());
TimeUnit.SECONDS.sleep(10);
return "success";
}
}
此类的作用是:让任务沉睡10s,然后返回一个“success”。
代码清单3:ScheduleThreadDemo
package org.4spaces;
import java.util.Date;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ScheduleThreadDemo {
public static void main(String[] args) throws InterruptedException,
ExecutionException {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(
2);
ScheduledFuture future1 = executor.schedule(new Task1(), 5,
TimeUnit.SECONDS);
ScheduledFuture future2 = executor.schedule(new LongTask(), 3,
TimeUnit.SECONDS);
BlockingQueue<ScheduledFuture> blockingQueue = new ArrayBlockingQueue<ScheduledFuture>(
2, true);
// 想BlockingQueue中存放对象,如果可以容纳,返回true,否则抛出异常
blockingQueue.add(future2);
blockingQueue.add(future1);
System.out.println(new Date());
// 如果BlockingQueue不为空
while (!blockingQueue.isEmpty()) {
// 取走BlockingQueue中排在首位的对象,取不到返回null
ScheduledFuture future = blockingQueue.poll();
// 如果没有执行
if (!future.isDone()) {
// 将任务再次加入队列
blockingQueue.add(future);
} else {
// 若果执行了,返回执行结果
System.out.println(future.get());
}
}
System.out.println(new Date());
executor.shutdown();
}
}
此类的作用是定时执行任务,我们定义了一个ScheduledThreadPoolExecutor,它的池长度为2,提交的任务中:第一个任务延迟5秒执行,第二个任务延迟3秒执行;然后我们定义了一个BlockingQueue,用它来存储ScheduleFuture,使用ScheduleFuture可以获得任务的执行结果,在一个while循环中,我们每次将一个ScheduledFuture从队列中弹出,验证它是否被执行,如果没有被执行则再次将它加入队列中,如果被执行了,这使用ScheduledFuture的get方法获取任务执行的结果。
看一下执行结果:
Mon Nov 03 20:39:15 CST 2014
LongTask running: Mon Nov 03 20:39:18 CST 2014
Task running :Mon Nov 03 20:39:20 CST 2014
dss2a2fffe
success
Mon Nov 03 20:39:28 CST 2014
从执行结果来看,长任务先执行,因为长任务延迟3s,然后是输出字符串任务,两个任务相差2s,任务从开始到结束时间差为13s,说明是多线程执行的。