我正在使用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();
}
}
}
}
答案 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)