#java #multithreading #task
#java #многопоточность #задача
Вопрос:
Я одновременно вычисляю три разных значения, которые зависят от состояния уровня моего приложения, поэтому я использую задачи для более быстрого вычисления. Однако, если я хочу изменить уровень во время вычисления, это невозможно, потому что все кнопки отключены во время вычисления.
Я обнаружил, что не могу отменить задачи, потому что мой графический интерфейс зависает до завершения задач. Поэтому я не могу отменить задачи, потому что они уже завершены
В моем графическом интерфейсе есть это событие buttonclick
buttonIncreaseLevel.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Platform.runLater(new Runnable() {
@Override
public void run() {
increaseLevelButtonActionPerformed(event);
}
});
}
});
Это увеличивает уровень и запускает этот метод
createTask(taskLeftEdge,EdgeType.LEFT);
createTask(taskBottomEdge,EdgeType.BOTTOM);
createTask(taskRightEdge,EdgeType.RIGHT);
pool.submit(taskRightEdge);
pool.submit(taskBottomEdge);
pool.submit(taskLeftEdge);
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("[Future] Started to wait for task (future)");
// A task is also its own future
ArrayList taskR = (ArrayList) taskRightEdge.get();
ArrayList taskB = (ArrayList) taskBottomEdge.get();
ArrayList taskL = (ArrayList) taskLeftEdge.get();
System.out.println("[Future] " taskR);
System.out.println("[Future] " taskB);
System.out.println("[Future] " taskL);
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(FUN3KochFractalFX.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
).start();
Метод создания задачи
private void createTask(Task task, EdgeType type){
if (task != null) {
application.cancelProgress(type);
task.cancel();
}
// There's a new task that performs some work
switch(type){
case LEFT:
taskLeftEdge = new EdgeGeneratorTask("Task: " taskNumber, type, this, application);
task = taskLeftEdge;
edges.addAll(koch.generateLeftEdge());
break;
case BOTTOM:
taskBottomEdge = new EdgeGeneratorTask("Task: " taskNumber, type, this, application);
task = taskBottomEdge;
edges.addAll(koch.generateBottomEdge());
break;
case RIGHT:
taskRightEdge = new EdgeGeneratorTask("Task: " taskNumber, type, this, application);
task = taskRightEdge;
edges.addAll(koch.generateRightEdge());
break;
}
taskNumber ;
application.setProgress( task, type);
}
И саму задачу. Класс Kochfractal — это место, где выполняются вычисления
private static final Logger LOG = Logger.getLogger(EdgeGeneratorTask.class.getName());
private final String id;
private EdgeType type;
private KochFractal calc;
private FUN3KochFractalFX application;
public EdgeGeneratorTask(String id, EdgeType type, KochManager manager, FUN3KochFractalFX main) {
this.id = id;
this.type = type;
calc = new KochFractal(manager);
application = main;
}
@Override
protected ArrayList<Edge> call() throws Exception {
ArrayList<Edge> edges = new ArrayList<>();
switch(type){
case LEFT:
edges = calc.generateLeftEdge();
break;
case BOTTOM:
edges = calc.generateBottomEdge();
break;
case RIGHT:
edges = calc.generateRightEdge();
break;
}
int MAX = edges.size();
for (int i = 1; i <= MAX; i ) {
if (isCancelled()) {
break;
}
updateProgress(i, MAX);
updateMessage(id " " i);
}
return edges;
}
Я ожидаю, что эти потоки будут отменены действием в моем графическом интерфейсе JavaFX.
Потоки должны выполняться в фоновом потоке, а не в самом потоке GUI
Комментарии:
1. Пожалуйста, покажите нам код метода CreateTask.
2. Примечание: поскольку события GUI, такие события действий уже выполняются в потоке приложения JavaFX, Platform.runLater обычно можно опустить. Код регистрации обработчика может быть уменьшен до:
buttonIncreaseLevel.setOnAction(this::increaseLevelButtonActionPerformed)
3. Я добавил метод createtask и саму задачу
4. Цикл for в EdgeGeneratorTask.call на самом деле не выполняет много итераций execpt по целому числу и обновляет графический интерфейс. Может быть, вы хотите поместить логику внутри цикла? Однако это не объясняет, почему графический интерфейс зависает…
5. Это больше похоже на то, что основной поток ожидает завершения выполнения задач, в то время как я использую Executorservice для отправки задач. Так это неправильный метод?