Java调度线程池ScheduledThreadPoolExecutor不执行问题怎么解决

其他教程   发布日期:2023年07月24日   浏览次数:443

本篇内容主要讲解“Java调度线程池ScheduledThreadPoolExecutor不执行问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java调度线程池ScheduledThreadPoolExecutor不执行问题怎么解决”吧!

    ScheduledThreadPoolExecutor不调度分析

    示例程序

    在示例程序可以看到当计数器中的计数达到5的时候就会主动抛出一个异常,抛出异常后

    1. ScheduledThreadPoolExecutor
    就不调度了。
    1. public class ScheduledTask {
    2. private static final AtomicInteger count = new AtomicInteger(0);
    3. private static final ScheduledThreadPoolExecutor SCHEDULED_TASK = new ScheduledThreadPoolExecutor(
    4. 1, new ThreadFactory() {
    5. @Override
    6. public Thread newThread(Runnable r) {
    7. Thread t = new Thread(Thread.currentThread().getThreadGroup(), r, "sc-task");
    8. t.setDaemon(true);
    9. return t;
    10. }
    11. });
    12. public static void main(String[] args) throws InterruptedException {
    13. CountDownLatch latch = new CountDownLatch(1);
    14. SCHEDULED_TASK.scheduleWithFixedDelay(() -> {
    15. System.out.println(111);
    16. if (count.get() == 5) {
    17. throw new IllegalArgumentException("my exception");
    18. }
    19. count.incrementAndGet();
    20. }, 0, 5, TimeUnit.SECONDS);
    21. latch.await();
    22. }
    23. }

    源码分析

    ScheduledThreadPoolExecutor#run

    run方法内部首先判断任务是不是周期性的任务,如果不是周期性任务通过

    1. ScheduledFutureTask.super.run();
    执行任务;如果状态是运行中或shutdown,取消任务执行;如果是周期性的任务,通过
    1. ScheduledFutureTask.super.runAndReset()
    执行任务并且重新设置状态,成功了就会执行
    1. setNextRunTime
    设置下次调度的时间,问题就是出现在
    1. ScheduledFutureTask.super.runAndReset()
    ,这里执行任务出现了异常,导致结果为false,就不进行下次调度时间设置等
    1. public void run() {
    2. boolean periodic = isPeriodic();
    3. if (!canRunInCurrentRunState(periodic))
    4. cancel(false);
    5. else if (!periodic)
    6. ScheduledFutureTask.super.run();
    7. else if (ScheduledFutureTask.super.runAndReset()) {
    8. setNextRunTime();
    9. reExecutePeriodic(outerTask);
    10. }
    11. }

    *FutureTask#runAndReset

    在线程任务执行过程中抛出异常,然后

    1. catch
    到了异常,最终导致这个方法返回false,然后
    1. ScheduledThreadPoolExecutor#run
    就不设置下次执行时间了,代码
    1. c.call();
    抛出异常,跳过
    1. ran = true;
    代码,最终
    1. runAndReset
    返回false。
    1. protected boolean runAndReset() {
    2. if (state != NEW ||
    3. !UNSAFE.compareAndSwapObject(this, runnerOffset,
    4. null, Thread.currentThread()))
    5. return false;
    6. boolean ran = false;
    7. int s = state;
    8. try {
    9. Callable<V> c = callable;
    10. if (c != null && s == NEW) {
    11. try {
    12. c.call(); // don't set result
    13. ran = true;
    14. } catch (Throwable ex) {
    15. setException(ex);
    16. }
    17. }
    18. } finally {
    19. // runner must be non-null until state is settled to
    20. // prevent concurrent calls to run()
    21. runner = null;
    22. // state must be re-read after nulling runner to prevent
    23. // leaked interrupts
    24. s = state;
    25. if (s >= INTERRUPTING)
    26. handlePossibleCancellationInterrupt(s);
    27. }
    28. return ran && s == NEW;
    29. }

    以上就是Java调度线程池ScheduledThreadPoolExecutor不执行问题怎么解决的详细内容,更多关于Java调度线程池ScheduledThreadPoolExecutor不执行问题怎么解决的资料请关注九品源码其它相关文章!