当用户输入TextField时:我需要通过WebRequest搜索一些数据并显示它们。
当用户键入多个字符时,应取消先前的下载并开始新的下载。
因此,当任务返回时,我使用Task下载数据和Service来显示数据。
s = new Service(){
@Override
protected Task createTask() {
return new Task<String>(){
@Override
protected String call() throws Exception {
//DOWNLOAD DATA
System.out.println("1");
Thread.sleep(1000);
System.out.println("2");
Thread.sleep(1000);
System.out.println("3");
Thread.sleep(1000);
return "banana";
}
};
}
};
s.setOnSucceeded(new EventHandler<WorkerStateEvent>(){
@Override
public void handle(WorkerStateEvent event) {
System.out.println(event.getSource().getValue() + " DISPLAYED");
}
});
//HANDLE KEY RELEASED ON A TEXTFIELD
public void onTextFieldKeyReleased() {
s.restart();
}
我注意到每次重新启动Service时都会出现另一个Thread,直到有一定数量的线程。 这使得程序显示数据有很大的延迟。
当KeyReleasedEvent发生时,我希望服务做的是取消当前正在运行的任务并启动一个新任务...每次新任务都不附加。
我怎样才能做到这一点?
答案 0 :(得分:0)
我无法再现你提到的延迟。
作为documented,Service
使用“some default executor”来执行Task
方法创建的createTask
。如果要修改默认行为,可以配置执行程序,例如:
s.setExecutor(Executors.newCachedThreadPool(runnable -> {
Thread t = new Thread(runnable);
t.setDaemon(true);
return t ;
});
显然,您可以使用您选择的任何执行者,具体取决于您的确切要求(在您的问题中并不清楚)。例如,如果你想限制(比方说)5个线程,你可以做
s.setExecutor(Executors.newFixedThreadPool(5, runnable -> {
Thread t = new Thread(runnable);
t.setDaemon(true);
return t ;
});
这是一个SSCCE。我添加了一些日志记录来跟踪服务的状态并显示用于该任务的线程:
import java.util.concurrent.Executors;
import javafx.application.Application;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class ServiceRestartTest extends Application {
@Override
public void start(Stage primaryStage) {
Service<Void> s = new Service<Void>(){
@Override
protected Task<Void> createTask() {
return new Task<Void>(){
@Override
protected Void call() throws Exception {
//DOWNLOAD DATA
System.out.println("New task on thread "+Thread.currentThread());
System.out.println("1");
Thread.sleep(1000);
System.out.println("2");
Thread.sleep(1000);
System.out.println("3");
Thread.sleep(1000);
return null;
}
};
}
};
s.setExecutor(Executors.newCachedThreadPool(runnable -> {
Thread t = new Thread(runnable);
t.setDaemon(true);
return t;
}));
s.stateProperty().addListener((obs, oldState, newState) -> System.out.println(newState));
TextField textField = new TextField();
textField.setOnKeyReleased(e -> s.restart());
primaryStage.setScene(new Scene(new StackPane(textField), 350, 120));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
输出,仅显示正在使用的两个线程:
SCHEDULED New task on thread Thread[Thread-5,5,main] 1 RUNNING CANCELLED READY SCHEDULED New task on thread Thread[Thread-6,5,main] 1 RUNNING CANCELLED READY SCHEDULED New task on thread Thread[Thread-6,5,main] 1 RUNNING CANCELLED READY SCHEDULED New task on thread Thread[Thread-6,5,main] 1 RUNNING CANCELLED READY SCHEDULED New task on thread Thread[Thread-6,5,main] 1 RUNNING CANCELLED READY SCHEDULED New task on thread Thread[Thread-6,5,main] 1 RUNNING 2 3 SUCCEEDED