Java并发编程与JavaFX场景嵌入技术解析
立即解锁
发布时间: 2025-08-19 02:14:55 阅读量: 2 订阅数: 8 


JavaFX 2:Java技术的富客户端开发指南
# Java并发编程与JavaFX场景嵌入技术解析
## 1. Java并发编程中的Service抽象类
在Java并发编程中,`Task<V>`类定义的是一次性任务,执行一次后便不会再次运行。而`Service<V>`抽象类则是`Worker`接口的一种可复用实现。
### 1.1 Service抽象类的特性
- **可重置状态**:`Service<V>`扩展了`Worker`的状态模型,允许将其状态重置为`Worker.State.READY`。
- **包含字段**:它包含一个`Task<V>`类型的字段和一个`java.util.concurrent.Executor`类型的字段。
- **额外属性**:除了`Worker`接口的九个只读属性外,`Service<V>`还有一个名为`executor`的`Executor`类型的读写属性。
### 1.2 Service类的方法
| 方法 | 描述 |
| --- | --- |
| `protected abstract Task createTask()` | 扩展`Service<V>`的类必须重写此方法以生成一个新创建的`Task`。 |
| `public void start()` | 仅当`Service<V>`对象处于`Worker.State.READY`状态时才能调用。它调用`createTask()`获取一个新的`Task`,并从`executor`属性获取一个`Executor`,若未设置则创建自己的`Executor`,然后将`Service<V>`对象的九个`Worker`属性绑定到`Task`的属性上,最后将`Task`转换到`Worker.State.SCHEDULED`状态并在`Executor`上执行。 |
| `public void reset()` | 仅当`Service<V>`的状态不是`Worker.State.SCHEDULED`或`Worker.State.RUNNING`时才能调用。它解除`Service<V>`的九个属性与底层`Task`的绑定,并将其值重置为初始值。 |
| `public void restart()` | 取消当前正在执行的`Task`(如果有),然后执行`reset()`,接着调用`start()`。 |
| `public final boolean cancel()` | 取消当前正在执行的`Task`(如果有);否则将`Service<V>`转换到`Worker.State.CANCELLED`状态。 |
### 1.3 ServiceExample示例代码
```java
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.IntegerBinding;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.SceneBuilder;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressBarBuilder;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFieldBuilder;
import javafx.scene.layout.BorderPaneBuilder;
import javafx.scene.layout.ColumnConstraintsBuilder;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.GridPaneBuilder;
import javafx.scene.layout.HBox;
import javafx.scene.layout.HBoxBuilder;
import javafx.stage.Stage;
import java.util.concurrent.atomic.AtomicBoolean;
public class ServiceExample extends Application {
private Model model;
private View view;
public static void main(String[] args) {
Application.launch(args);
}
public ServiceExample() {
model = new Model();
}
@Override
public void start(Stage stage) throws Exception {
view = new View(model);
hookupEvents();
stage.setTitle("Service Example");
stage.setScene(view.scene);
stage.show();
}
private void hookupEvents() {
view.startButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
model.shouldThrow.getAndSet(false);
((Service) model.worker).restart();
}
});
view.cancelButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
model.worker.cancel();
}
});
view.exceptionButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
model.shouldThrow.getAndSet(true);
}
});
}
private static class Model {
public Worker<String> worker;
public AtomicBoolean shouldThrow = new AtomicBoolean(false);
public IntegerProperty numberOfItems = new SimpleIntegerProperty(250);
private Model() {
worker = new Service<String>() {
@Override
protected Task createTask() {
return new Task<String>() {
@Override
protected String call() throws Exception {
updateTitle("Example Service");
updateMessage("Starting...");
final int total = numberOfItems.get();
updateProgress(0, total);
for (int i = 1; i <= total; i++) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
return "Canceled at " + System.currentTimeMillis();
}
if (shouldThrow.get()) {
throw new RuntimeException("Exception thrown at " + System.currentTimeMillis());
}
updateTitle("Example Service (" + i + ")");
updateMessage("Processed " + i + " of " + total + " items.");
updateProgress(i, total);
}
return "Completed at " + System.currentTimeMillis();
}
};
}
};
}
}
private static class View {
public ProgressBar progressBar;
public Label title;
public Label message;
public Label running;
public Label state;
public Label totalWork;
public Label workDone;
public Label progress;
public Label value;
public Label exception;
public TextField numberOfItems;
public Button startButton;
public Button cancelButton;
public Button exceptionButton;
public Scene scene;
private View(final Model model) {
progressBar = ProgressBarBuilder.create()
.minWidth(250)
.build();
title = new Label();
message = new Label();
running = new Label();
state = new Label();
totalWork = new Label();
workDone = new Label();
progress = new Label();
value = new Label();
exception = new Label();
numberOfItems = TextFieldBuilder.create()
.maxWidth(40)
.build();
startButton = new Button("Start");
cancelButton = new Button("Cancel");
exceptionButton = new Button("Exception");
final ReadOnlyObjectProperty<Worker.State> stateProperty =
model.worker.stateProperty();
progressBar.progressProperty().bind(model.worker.progressProperty());
title.textProperty().bind(
model.worker.titleProperty());
message.textProperty().bind(
model.worker.messageProperty());
running.textProperty().bind(
Bindings.format("%s", model.worker.runningProperty()));
state.textProperty().bind(
Bindings.format("%s", stateProperty));
totalWork.textProperty().bind(
model.worker.totalWorkProperty().asString());
workDone.textProperty().bind(
model.worker.workDoneProperty().asString());
progress.textProperty().bind(
Bindings.format("%5.2f%%", model.worker.progressProperty().multiply(100)));
value.textProperty().bind(
model.worker.valueProperty());
exception.textProperty().bind(new StringBinding() {
{
super.bind(model.worker.exceptionProperty());
}
@Override
protected String computeValue() {
final Throwable exception = model.worker.getException();
if (exception == null) return "";
return exception.getMessage();
}
});
model.numberOfItems.bind(new IntegerBinding() {
{
super.bind(numberOfItems.textProperty());
}
@Override
protected int computeValue() {
final String text = numberOfItems.getText();
int n = 250;
try {
n = Integer.parseInt(text);
} catch (NumberFormatException e) {
}
return n;
}
});
startButton.disableProperty().bind(
stateProperty.isEqualTo(Worker.State.RUNNING));
cancelButton.disableProperty().bind(
stateProperty.isNotEqualTo(Worker.State.RUNNING));
exceptionButton.disableProperty().bind(
stateProperty.isNotEqualTo(Worker.State.RUNNING));
final HBox topPane = HBoxBuilder.create()
.padding(new Insets(10, 10, 10, 10))
.spacing(10)
.alignment(Pos.CENTER)
.children(progressBar)
.build();
final GridPane centerPane = GridPaneBuilder.create()
.hgap(10)
.vgap(10)
.padding(new Insets(10, 10, 10, 10))
.columnConstraints(
ColumnConstraintsBuilder.create()
.halignment(HPos.RIGHT)
.minWidth(65)
.build(),
ColumnConstraintsBuilder.create()
.halignment(HPos.LEFT)
.minWidth(200)
.build()
)
.build();
centerPane.add(new Label("Title:"), 0, 0);
centerPane.add(new Label("Message:"), 0, 1);
centerPane.add(new Label("Running:"), 0, 2);
centerPane.add(new Label("State:"), 0, 3);
centerPane.add(new Label("Total Work:"), 0, 4);
centerPane.add(new Label("Work Done:"), 0, 5);
centerPane.add(new Label("Progress:"), 0, 6);
centerPane.add(new Label("Value:"), 0, 7);
centerPane.add(new Label("Exception:"), 0, 8);
centerPane.add(title, 1, 0);
centerPane.add(message, 1, 1);
centerPane.add(running, 1, 2);
centerPane.add(state, 1, 3);
centerPane.add(totalWork, 1, 4);
centerPane.add(workDone, 1, 5);
centerPane.add(progress, 1, 6);
centerPane.add(value, 1, 7);
centerPane.add(exception, 1, 8);
final HBox buttonPane = HBoxBuilder.create()
.padding(new Insets(10, 10, 10, 10))
.spacing(10)
.alignment(Pos.CENTER)
.children(new Label("Process"), numberOfItems, new Labe
```
0
0
复制全文
相关推荐










