Java调度线程池ScheduledThreadPoolExecutor不执行问题怎么解决
本文讲解"Java调度线程池ScheduledThreadPoolExecutor不执行问题如何解决",希望能够解决相关问题。
ScheduledThreadPoolExecutor不调度分析
示例程序
在示例程序可以看到当计数器中的计数达到5的时候就会主动抛出一个异常,抛出异常后ScheduledThreadPoolExecutor就不调度了。
public class ScheduledTask { private static final AtomicInteger count = new AtomicInteger(0); private static final ScheduledThreadPoolExecutor SCHEDULED_TASK = new ScheduledThreadPoolExecutor( 1, new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = new Thread(Thread.currentThread().getThreadGroup(), r, "sc-task"); t.setDaemon(true); return t; } }); public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(1); SCHEDULED_TASK.scheduleWithFixedDelay(() -> { System.out.println(111); if (count.get() == 5) { throw new IllegalArgumentException("my exception"); } count.incrementAndGet(); }, 0, 5, TimeUnit.SECONDS); latch.await(); } }
源码分析
ScheduledThreadPoolExecutor#run
run方法内部首先判断任务是不是周期性的任务,如果不是周期性任务通过ScheduledFutureTask.super.run();执行任务;如果状态是运行中或shutdown,取消任务执行;如果是周期性的任务,通过ScheduledFutureTask.super.runAndReset()执行任务并且重新设置状态,成功了就会执行setNextRunTime设置下次调度的时间,问题就是出现在ScheduledFutureTask.super.runAndReset(),这里执行任务出现了异常,导致结果为false,就不进行下次调度时间设置等
public void run() { boolean periodic = isPeriodic(); if (!canRunInCurrentRunState(periodic)) cancel(false); else if (!periodic) ScheduledFutureTask.super.run(); else if (ScheduledFutureTask.super.runAndReset()) { setNextRunTime(); reExecutePeriodic(outerTask); } }
*FutureTask#runAndReset
在线程任务执行过程中抛出异常,然后catch到了异常,最终导致这个方法返回false,然后ScheduledThreadPoolExecutor#run就不设置下次执行时间了,代码c.call(); 抛出异常,跳过ran = true;代码,最终runAndReset返回false。
protected boolean runAndReset() { if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return false; boolean ran = false; int s = state; try { Callable<V> c = callable; if (c != null && s == NEW) { try { c.call(); // don't set result ran = true; } catch (Throwable ex) { setException(ex); } } } finally { // runner must be non-null until state is settled to // prevent concurrent calls to run() runner = null; // state must be re-read after nulling runner to prevent // leaked interrupts s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } return ran && s == NEW; }
关于 "Java调度线程池ScheduledThreadPoolExecutor不执行问题如何解决" 就介绍到此。希望多多支持编程宝库。
本文讲解"Java判断ip是否为IPV4或IPV6地址的方式有哪些",希望能够解决相关问题。判断字符串是否为IP地址通常都是基于正则表达式实现的,无论是引入外部的依赖包亦或是自己写正 ...