ScheduledExecutorService执行周期任务遇到异常会终止

Sat Aug 08 13:50:14 CST 2015 2954 Java

文章摘要并发编程中,在需要做一些定时周期任务时往往需要用到ScheduledExecutorService,但是如果某一次执行任务遇到异常,则会终止后续任务的执行。

多线程编程中,在需要做一些定时周期任务时往往需要用到ScheduledExecutorService,但是使用ScheduledExecutorService类的话,如果某一次执行任务遇到异常,则会终止后续任务的执行。

/**
     * Creates and executes a periodic action that becomes enabled first
     * after the given initial delay, and subsequently with the given
     * period; that is executions will commence after
     * <tt>initialDelay</tt> then <tt>initialDelay+period</tt>, then
     * <tt>initialDelay + 2 * period</tt>, and so on.
     * If any execution of the task
     * encounters an exception, subsequent executions are suppressed.
     * Otherwise, the task will only terminate via cancellation or
     * termination of the executor.  If any execution of this task
     * takes longer than its period, then subsequent executions
     * may start late, but will not concurrently execute.
     *
     * @param command the task to execute
     * @param initialDelay the time to delay first execution
     * @param period the period between successive executions
     * @param unit the time unit of the initialDelay and period parameters
     * @return a ScheduledFuture representing pending completion of
     *         the task, and whose <tt>get()</tt> method will throw an
     *         exception upon cancellation
     * @throws RejectedExecutionException if the task cannot be
     *         scheduled for execution
     * @throws NullPointerException if command is null
     * @throws IllegalArgumentException if period less than or equal to zero
     */
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit);

通过看ScheduledExecutorService接口的源代码,可以发现scheduleAtFixedRate的注释中说明了,如果某次任务执行过程中遇到了异常,那么后续任务将会被终止(

If any execution of the task encounters an exception, subsequent executions are suppressed.)

也就是说,Runnable command里面的run方法如果抛出了异常的话,那么这个任务就不能周期性地被执行了。

看如下代码:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Test {
	public static void main(String[] args) {
		ScheduledExecutorService s = Executors.newScheduledThreadPool(1);
		s.scheduleAtFixedRate(new Runner(), 0, 2, TimeUnit.SECONDS);
	}
	
	static class Runner implements Runnable {

		@Override
		public void run() {
			int[] array = new int[1];
			array[0] = 0;
			System.out.println("run...");
			System.out.println(array[1]);
		}
		
	}
}

run()方法中明显数组越界,所以Runner.run()这个任务只会被执行一次,而且控制台中也没有任何Exception信息输出!如果对ScheduledExecutorService不熟悉,在开发过程中不知道周期任务遇到异常不会继续执行以后的任务,找bug估计都得找很久。


那么怎么实现即使某次任务出现异常也继续往下执行呢?可以在run里面加上try catch,在run里面把异常处理了,不往上抛。

打赏
打赏

分享到: