java 取消任务_java – 如果启动新的任务实例,如何取消任务?

正如this answer所提到的,您的要求似乎是使用Service的完美原因.服务允许您以可重用的方式在任何给定时间运行一个任务.当您通过Service.cancel()取消服务时,它会取消基础任务.该服务还会为您跟踪自己的任务,因此您无需将它们保存在某个列表中.

使用您的MVCE您想要做的是创建一个包装您的任务的服务.每次用户在ListView中选择新项目时,您都将取消服务,更新必要的状态,然后重新启动服务.然后,您将使用Service.setOnSucceeded回调将结果设置为Label.这可以保证只返回最后一次成功执行.即使先前取消的任务仍然返回结果,服务也会忽略它们.

您也不必担心外部同步(至少在您的MVCE中).处理启动,取消和观察服务的所有操作都发生在FX线程上.在FX线程上没有执行的唯一一段代码(如下所示)将在Task.call()内部(好吧,以及在实例化类时我们认为发生在JavaFX-Launcher线程上的直接分配的字段).

以下是使用服务修改的MVCE版本:

import javafx.application.Application;

import javafx.concurrent.Service;

import javafx.concurrent.Task;

import javafx.geometry.Insets;

import javafx.geometry.Pos;

import javafx.scene.Scene;

import javafx.scene.control.Label;

import javafx.scene.control.ListView;

import javafx.scene.layout.VBox;

import javafx.stage.Stage;

public class Main extends Application {

private final ListViewFailed(wse -> {

// you could also show an Alert to the user here

service.getException().printStackTrace();

service.reset();

});

// Simple UI

VBox root = new VBox(5);

root.setAlignment(Pos.CENTER);

root.setPadding(new Insets(10));

root.getChildren().addAll(listView,"Five"

);

listView.getSelectionModel().selectedItemProperty().addListener((observableValue,newValue) -> {

if (service.isRunning()) {

service.cancel();

service.reset();

}

service.setSelected(newValue);

service.start();

});

stage.setScene(new Scene(root));

stage.show();

}

private static class QueryService extends Service

当您调用Service.start()时,它会创建一个Task并使用其executor property中包含的当前Executor执行它.如果该属性包含null,则它使用一些未指定的默认Executor(使用守护程序线程).

在上面,你看到我取消后在onSucceeded和onFailed回调中调用reset().这是因为只有在READY state中才能启动服务.如果需要,可以使用restart()而不是start().它基本上等同于调用cancel() – > reset() – > start().

1任务无法恢复.相反,服务每次启动时都会创建一个新任务.

取消服务时,取消当前正在运行的任务(如果有).即使服务,因此任务,已被取消并不意味着执行已经实际停止.在Java中,取消后台任务需要与所述任务的开发者合作.

这种合作采取定期检查执行是否应该停止的形式.如果使用普通的Runnable或Callable,则需要检查当前Thread的中断状态或使用一些boolean flag2.由于Task扩展了FutureTask,您还可以使用从Future接口继承的isCancelled()方法.如果由于某种原因你不能使用isCancelled()(称为外部代码,不使用任务等等),那么你使用以下方法检查线程中断:

>静态方法

>只能检查当前线程

>清除当前线程的中断状态

>实例方法

>可以检查您有引用的任何线程

>不清除中断状态

您可以通过Thread.currentThread()获取对当前线程的引用.

在您的后台代码中,如果当前线程已被中断,布尔标志已设置或任务已被取消,您需要在适当的位置进行检查.如果有,那么你将执行任何必要的清理并停止执行(通过返回或抛出异常).

此外,如果您的线程正在等待某些可中断操作,例如阻塞IO,那么它将在中断时抛出InterruptedException.在您的MVCE中,您使用Thread.sleep,它是可中断的;这意味着当你调用cancel时,这个方法会抛出提到的异常.

当我说上面的“清理”时,我的意思是在后台需要清理,因为你还在后台线程上.如果您需要清理FX线程上的任何内容(例如更新UI),那么您可以使用Service的onCancelled属性.

在上面的代码中,您还将看到我使用protected methods succeeded()和cancel(). Task和Service都提供了这些方法(以及各种Worker.States的其他方法),并且它们将始终在FX线程上调用.但是,请阅读文档,因为ScheduledService要求您调用其中某些方法的超级实现.

2如果使用布尔标志,请确保其他线程可以看到对它的更新.您可以通过使其变得易变,同步或使用java.util.concurrent.atomic.AtomicBoolean来实现此目的.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值