程序Triathlon执行长时间运行的任务,如果任务已完全执行,可以再次重新启动它。我想添加停止执行以重置UI的可能性。为此,我添加了一个新按钮,停止。这是代码:
package triathlon2;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.*;
import javafx.beans.property.*;
import javafx.beans.value.*;
import javafx.concurrent.Task;
import javafx.event.*;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Triathlon2 extends Application
{
private final Random random = new Random();
private final ExecutorService exec = Executors.newSingleThreadExecutor();
final TaskMonitor taskMonitor = new TaskMonitor();
final ProgressIndicator progressIndicator
= new ProgressIndicator();
@Override public void start(Stage stage) throws Exception
{
progressIndicator.progressProperty()
.bind(taskMonitor.currentTaskProgressProperty());
final Label currentRaceStage = new Label();
currentRaceStage.textProperty()
.bind(taskMonitor.currentTaskNameProperty());
createMainLayout(
stage,
createStartRaceButton(
exec,
taskMonitor
),
createStopButton(
//exec,
taskMonitor
),
createRaceProgressView(
taskMonitor,
progressIndicator,
currentRaceStage
)
);
}
@Override public void stop() throws Exception
{
exec.shutdownNow();
}
private Button createStartRaceButton(
final ExecutorService exec,
final TaskMonitor taskMonitor)
{
final Button startButton = new Button("Start Race");
startButton.disableProperty()
.bind(taskMonitor.idleProperty().not());
startButton.setOnAction((ActionEvent actionEvent) ->
{
runRace(exec, taskMonitor);
});
return startButton;
}
private Button createStopButton(
//final ExecutorService exec,
final TaskMonitor taskMonitor)
{
final Button stopButton = new Button("Stop Race");
stopButton.disableProperty()
.bind(taskMonitor.idleProperty());
stopButton.setOnAction((ActionEvent actionEvent) ->
{
exec.shutdownNow();
Platform.setImplicitExit(true);
});
return stopButton;
}
private HBox createRaceProgressView(
final TaskMonitor taskMonitor,
ProgressIndicator progressIndicator,
Label currentRaceStage)
{
final HBox raceProgress = new HBox(10);
raceProgress.getChildren().setAll(
currentRaceStage,
progressIndicator
);
raceProgress.setOpacity(0);
raceProgress.setAlignment(Pos.CENTER);
final FadeTransition fade
= new FadeTransition(
Duration.seconds(0.75), raceProgress);
fade.setToValue(0);
taskMonitor.idleProperty()
.addListener((Observable observable) ->
{
if (taskMonitor.idleProperty().get())
{
fade.playFromStart();
} else
{
fade.stop();
raceProgress.setOpacity(1);
}
});
return raceProgress;
}
private void createMainLayout(Stage stage, Button startButton, Button stopButton, HBox raceProgress)
{
final VBox layout = new VBox(10);
layout.getChildren().setAll(
raceProgress,
startButton,stopButton
);
layout.setAlignment(Pos.CENTER);
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10px;");
stage.setScene(new Scene(layout, 500, 600));
stage.show();
}
private void runRace(ExecutorService exec, TaskMonitor taskMonitor)
{
StageTask swimTask = new StageTask("Swim", 30, 40);
StageTask bikeTask = new StageTask("Bike", 210, 230);
StageTask runTask = new StageTask("Run", 120, 140);
taskMonitor.monitor(swimTask, bikeTask, runTask);
exec.execute(swimTask);
exec.execute(bikeTask);
exec.execute(runTask);
}
class TaskMonitor {
final private ReadOnlyObjectWrapper<StageTask> currentTask = new ReadOnlyObjectWrapper<>();
final private ReadOnlyStringWrapper currentTaskName = new ReadOnlyStringWrapper();
final private ReadOnlyDoubleWrapper currentTaskProgress = new ReadOnlyDoubleWrapper();
final private ReadOnlyBooleanWrapper idle = new ReadOnlyBooleanWrapper(true);
public void monitor(final StageTask task)
{
task.stateProperty().addListener(new ChangeListener<Task.State>()
{
@Override
public void changed(ObservableValue<? extends Task.State> observableValue, Task.State oldState, Task.State state)
{
switch (state)
{
case RUNNING:
currentTask.set(task);
currentTaskProgress.unbind();
currentTaskProgress.set(task.progressProperty().get());
currentTaskProgress.bind(task.progressProperty());
currentTaskName.set(task.nameProperty().get());
idle.set(false);
break;
case SUCCEEDED:
case CANCELLED:
case FAILED:
task.stateProperty().removeListener(this);
idle.set(true);
break;
}
}
});
}
public void monitor(final StageTask... tasks)
{
for (StageTask task: tasks) {
monitor(task);
}
}
public ReadOnlyObjectProperty<StageTask> currentTaskProperty()
{
return currentTask.getReadOnlyProperty();
}
public ReadOnlyStringProperty currentTaskNameProperty()
{
return currentTaskName.getReadOnlyProperty();
}
public ReadOnlyDoubleProperty currentTaskProgressProperty()
{
return currentTaskProgress.getReadOnlyProperty();
}
public ReadOnlyBooleanProperty idleProperty()
{
return idle.getReadOnlyProperty();
}
}
class StageTask extends Task<Duration>
{
final private ReadOnlyStringWrapper name;
final private int minMinutesElapsed;
final private int maxMinutesElapsed;
public StageTask(String name, int minMinutesElapsed, int maxMinutesElapsed)
{
this.name = new ReadOnlyStringWrapper(name);
this.minMinutesElapsed = minMinutesElapsed;
this.maxMinutesElapsed = maxMinutesElapsed;
}
@Override protected Duration call() throws Exception
{
Duration duration = timeInRange(
minMinutesElapsed, maxMinutesElapsed
);
for (int i = 0; i < 25; i++)
{
updateProgress(i, 25);
Thread.sleep((int) (duration.toMinutes()));
}
updateProgress(25, 25);
return duration;
}
private Duration timeInRange(int min, int max)
{
return Duration.minutes(
random.nextDouble() * (max - min) + min
);
}
public ReadOnlyStringProperty nameProperty()
{
return name.getReadOnlyProperty();
}
}
public static void main(String[] args)
{
Application.launch(Triathlon2.class);
}
}
如果任务已完成,程序将重新启动,但如果在停止后调用start,则程序将崩溃。我该怎么说?
答案 0 :(得分:0)
您在此处遇到的基本逻辑错误是您尝试在Executor
上启动Shutdown
后向其提交任务。来自Java doc
启动以前提交的任务的有序关闭 已执行,但不会接受任何新任务
我们在点击shutdownNow()
按钮时为exec
调用了Stop Race
方法。在此之后,exec
无法接受任何进一步的任务。
P.S。由于您的exec
是最终版,因此您无法重新实例化它!