如何在Spring ThreadPoolTask​​Scheduler中找到未来

时间:2018-10-17 10:03:37

标签: java spring scheduling

我正在使用Spring ThreadPoolTaskScheduler,因此我需要在某种条件下查找并取消将来。

ScheduledFuture任务中有一个Runnable字段并将任务收集到ArrayList中是否正确?我应该使用CopyOnWriteArrayList吗?

class Task implements Runnable {
  public Task(int id) {
    this.id = id;
  }
  private final int id;
  private ScheduledFuture future;
  public void setFuture(ScheduledFuture future) {
    this.future = future;
  }
  public ScheduledFuture getFuture() {
    return future;
  }
  public int getId() {
    return this.id;
  }
  public void run() {
    System.out.println(this.id);
  }
}

@Service
@RequiredArgsConstructor
public class ServiceTest {
  private final ThreadPoolTaskScheduler threadPoolTaskScheduler;
  private final ArrayList<Task> tasks = new ArrayList<Task>();
  @PostConstruct
  public void registerTasks() {
    for (int i = 0; i < 3; i++) {
      Task task = new Task(i);
      ScheduledFuture future = threadPoolTaskScheduler.schedule(task, new 
      PeriodicTrigger(100));
      task.setFuture(future);
      tasks.add(task);
    }
  }
  public void stopTask(int id) {
    Iterator<Task> it = tasks.iterator();
    while(it.hasNext()) {
      Task task = it.next();
      if (task.getId() == id) {
        task.getFuture().cancel(false);
        it.remove();
      }
    }
  }
}

1 个答案:

答案 0 :(得分:0)

在Runnable任务中具有ScheduledFuture字段是否正确?

从纯粹的技术角度来看,我认为将ScheduledFuture存储在实现Runnable的Task类的实例中不会有任何问题,因为Task类实例只会将其存储为状态信息,您可以使用就像您在 stopTask()方法中所做的一样。另外,在此仅需注意,您使用的是PeriodicTrigger,这意味着线程将在提供的100 ms时间间隔后继续执行,除非取消了任务。

注意:请确保您的实际run()方法将来不会以任何方式更改类变量。 (尽管问题中没有这样做,但是您的实际代码也不应从run()方法内部对future变量进行任何此类更改)

将任务收集到ArrayList中?我应该使用CopyOnWriteArrayList吗?

在这里使用ArrayList并没有什么害处,因为您是在任何多线程上下文中使用它的。如果该列表应该在多线程上下文中使用,那么您可能会想到使用CopyOnWriteArrayList。确切地说,您的ServiceTest类具有一个registerTasks()方法,该方法正在修改/访问您的列表,并且按照问题所示的代码,该方法未以多线程方式被调用。因此,这里不需要CopyOnWriteArrayList。

此外,如果需要,您还可以使用对cancel方法的调用返回的布尔值来检查任务是否被取消。您可能要使用它来执行任何进一步的操作。


更新: 哦,好吧,我忽略了通过迭代器进行的修改。我同意,如果可以通过REST控制器调用 stopTask()方法,则可以通过多线程方式对其进行访问。但是,CopyOnWriteArrayList在其iterator()上不支持remove()方法,以防万一您正在考虑使用该方法。另外,仅当列表上的写入操作比读取操作多时,才建议使用CopyOnWriteArrayList。实际上,这是为了安全遍历,其中大多数是使用迭代器进行的读取操作。我建议同步 stopTask()方法或使用 Collections.synchronizedList(tasks)