赞
踩
ScheduledExecutorService 的主要功能是将定时任务与线程池结合使用,网络上有很多博客对ScheduledExecutorService进行了分析,同时与Timer进行的比对。因此本篇不在对此进行描述,本篇主要描述使用ScheduledExecutorService的注意事项。
ScheduledExecutorService的构造函数源码是
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
由于ScheduledThreadPoolExecutor的父类是ThreadPoolExecutor,因此构造函数可以是以下表现形式
ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
根据线程池参数的理解,分析如下
延迟指定时间后,运行Runnable任务,Runnable的任务是没有返回值的,且不会向调用这抛出异常。
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
延迟指定时间后,运行Callable任务,Callable的任务有返回值,且通过get接口可以获取任务返回值和抛出的异常。
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
初次延迟initialDelay时间后,执行Runnable 任务,间隔period后,再次执行。当Runnable执行时间大于period,则间隔时间为Runnable的执行时间;当Runnable执行时间小于period,则间隔时间为period。在period和Runnable 时间具有可比性的时候,具有一定的影响。
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
初次延迟initialDelay时间后,执行Runnable 任务,之后间隔delay后,再次执行。注意间隔时间为任务执行时间+delay时间。任务之间的间隔时间是固定的。
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
当核心工作线程数大于提交给线程池任务的数量时,代码中设置的延迟时间和隔间时间才是准确的。因此为了时间的准确性需要预先保证当核心工作线程数大于提交给线程池任务的数量。当提交的任务数无法确定时,最好自定义线程池,来满足时间的准确性问题。
当任务必须执行成功时,必须考虑使用接口public <V> ScheduledFuture<V> schedule(Callable<V> callable,long delay, TimeUnit unit);
通过返回值判断任务是否执行成功,如果执行失败,则可以把任务做一定的重试策略,重新添加到线程中执行。代码如下
private void test3(){ Log.d(TAG, "===提交任务1==="+ DateUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss")); ret = scheduledThreadPool.schedule(callable,3000,TimeUnit.MILLISECONDS); new Thread(new Runnable() { @Override public void run() { try { String strRet = ret.get(); Log.d(TAG,"ret = "+strRet); if ("执行失败".equals(strRet)){ // 再次执行, ret = scheduledThreadPool.schedule(callable,3000,TimeUnit.MILLISECONDS); } } catch (ExecutionException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }
从java提供的接口来看,执行周期性任务无法获取执行结果,这样的原因是,scheduleAtFixedRate
和scheduleWithFixedDelay
。调用的源码是
// 核心是这个,sft是无返回指的,如果需要返回值,需要自定义线程池。
ScheduledFutureTask<Void> sft =
new ScheduledFutureTask<Void>(command,
null,
triggerTime(initialDelay, unit),
unit.toNanos(period),
sequencer.getAndIncrement());
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
sft.outerTask = t;
delayedExecute(t);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。