今天,我们接着上篇文章,继续来说我们的时时调度。前两个例子我们调用的方法都是没有返回值得,可是实际应用中,一般的方法都是有返回值得,我们这次来修改一下,看看有返回值得方法如何做到时时调度。
一、时时调度变形
1、控制类
public class timeTest {
/**
* 时时调度
* 3秒后开始,每隔1秒打印一次
*/
public static String executePerDay() {
// 创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
System.out.println("时时调度");
System.out.println("getTest()"+ new Date().toString());
Future future =executor.schedule(
new returnTest(), //调用执行方法的类
3000, //延迟3秒后执行
TimeUnit.MILLISECONDS);
String result="";
try {
//取出返回结果
result = future.get().toString();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
}
2、真正执行者
public class returnTest implements Callable<String> {
@Override
public String call() throws Exception {
//调用实际执行的方法
return getNowTime();
}
private String getNowTime(){
//打印测试时间
String result="getTest()"+ new Date().toString();
System.out.println(result);
return result;
}
}
3、主类
public class mainTest {
public static void main(String[] args) {
timeTest test = new timeTest();
//时时调度
String result=test.executePerDay();
System.out.println("收到--"+result);
}
}
二、分析
1、Executors(线程池)
从JAVA5开始新增了一个Executors工具类来产生线程池,它有如下几个静态工厂方法来创建线程池。
public static ExecutorService newFixedThreadPool(int nThreads)
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,
则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。
public static ExecutorService newSingleThreadExecutor()
创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程,那么如果需要,一个新线程将代替它执行后续的任务)。
可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。与其他等效的newFixedThreadPool(1)不同,可保证不能对ThreadPoolExecutor重新进行配置来使用更多的线程。
注意:newSingleThreadExecutor与newFixedThreadPool(1)不同之出在于:
newSingleThreadExecutor返回的ExcutorService在析构函数finalize()会调用shutdown(),即如果我们没有对它调用shutdown(),那么可以确保它在被回收时调用shutdown()来终止线程。
2、ScheduledExecutorService(任务调度)
在ExecutorService的基础上,ScheduledExecutorService提供了按时间安排执行任务的功能,它提供的方法主要有:
schedule(task,initDelay):安排所提交的Callable或Runnable任务在initDelay指定的时间后执行。//可以用来延迟执行有返回值的任务
scheduleAtFixedRate():安排所提交的Runnable任务按指定的间隔重复执行。//可以用来执行周期性任务
scheduleWithFixedDelay():安排所提交的Runnable任务在每次执行完后,等待delay所指定的时间后重复执行。//可以用来执行周期性定时任务
3、Future(接受返回参数)
Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。
计算完成后只能使用 get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由 cancel 方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。
总结:
关于时时调度,我们现在可以时时或定时调用任意的方法,但是有一个问题,那就是在调用有返回值得方法时,我们只能延迟调用,却不能周期性的调用。对于这点,我们会在以后的学习过程中,采用其他方式解决。