如何让后续代码在ScheduledExecutorService执行完成后再运行
问题1:实现后续代码等待定时任务完全结束后执行
ScheduledExecutorService的调度逻辑默认异步运行在后台线程,主线程提交任务后不会主动阻塞,会直接执行后续代码。你可以通过awaitTermination方法实现主线程阻塞等待调度器完全终止:
- 提交调度任务后,在主线程新增阻塞等待逻辑:
executorService.scheduleAtFixedRate(runnable, 5, 5, TimeUnit.SECONDS); // 阻塞等待调度器完全终止,可根据业务场景设置合理超时时间 try { executorService.awaitTermination(1, TimeUnit.DAYS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("等待调度器终止被中断", e); } System.out.println("Executor ended"); // 后续业务代码、API调用逻辑放在此处即可保证在调度器结束后执行
- 注意:你当前代码中调用的
shutdown()方法只会停止接收新任务,已提交的待运行/运行中任务仍会正常执行完毕,配合awaitTermination即可保证所有定时任务跑完后再执行后续逻辑。
问题2:调度任务内部访问变量的问题
你遇到的无法访问变量的问题是Java匿名内部类的语法限制导致的,可按如下规则处理:
- 类的成员变量(即你说的全局变量)只要权限修饰符允许,匿名Runnable内部可以直接访问,无额外限制。
- 如果要访问方法内的局部变量,Java要求该变量必须是
final修饰或实际不可变(effectively final),如果需要在内部修改变量值,可将变量封装为原子类或自定义对象容器,示例如下:
// 要修改的boolean标记用AtomicBoolean封装 AtomicBoolean stopFlag = new AtomicBoolean(false); Runnable runnable = new Runnable() { public void run() { // 内部可直接读取、修改原子类变量 if (stopFlag.get()) { executorService.shutdown(); } } };
完整可运行示例代码
import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; public class ScheduledTaskDemo { // 类成员变量可直接在匿名内部类访问 private static String globalConfig = "demoConfig"; public static void main(String[] args) { AtomicBoolean stopCondition = new AtomicBoolean(false); ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); Runnable runnable = new Runnable() { int runTimes = 0; public void run() { try { runTimes++; System.out.println("任务第"+runTimes+"次执行,全局变量值:"+globalConfig); // 模拟API调用返回结果,假设执行3次满足停止条件 if (runTimes >= 3) { stopCondition.set(true); executorService.shutdown(); System.out.println("满足停止条件,触发调度器关闭"); } } catch (Exception ex) { System.out.println("调度任务执行异常: " + ex); executorService.shutdown(); } } }; executorService.scheduleAtFixedRate(runnable, 5, 5, TimeUnit.SECONDS); // 阻塞等待调度器完全终止 try { executorService.awaitTermination(1, TimeUnit.DAYS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("等待调度器终止被中断", e); } System.out.println("调度器完全结束,执行后续业务逻辑"); System.out.println("停止标记值:" + stopCondition.get()); } }
内容的提问来源于stack exchange,提问作者Lara
相关产品推荐
相关产品推荐

