服务有一个签名Service<V>
,它<V>
是一个通用类型参数,用于从服务提供的任务中指定返回对象的类型。
假设您要定义一个返回 Foo 类型的用户定义对象的服务,那么您可以这样做:
class FooGenerator extends Service<Foo> {
protected Task createTask() {
return new Task<Foo>() {
protected Foo call() throws Exception {
return new Foo();
}
};
}
}
要使用该服务:
FooGenerator fooGenerator = new FooGenerator();
fooGenerator.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override public void handle(WorkerStateEvent t) {
Foo myNewFoo = fooGenerator.getValue();
System.out.println(myNewFoo);
}
});
fooGenerator.start();
如果要在每次启动或重新启动服务之前将输入值传递给服务,则必须更加小心。您可以将要输入的值作为服务上的可设置成员添加到服务中。在调用服务的 start 方法之前,可以从 JavaFX 应用程序线程调用这些设置器。然后,当创建服务的任务时,将参数传递给服务的任务的构造函数。
这样做时,最好使所有信息在线程之间来回传递不可变。对于下面的示例,Foo 对象作为输入参数传递给服务,Foo 对象基于作为服务输出接收的输入。但是 Foo 本身的状态只在它的构造函数中初始化 - Foo 的实例是不可变的,一旦创建就不能改变,它的所有成员变量都是最终的,不能改变。这使得推理程序变得更加容易,因为您永远不必担心另一个线程可能会同时覆盖状态。这似乎有点复杂,但它确实让一切都非常安全。
class FooModifier extends Service<Foo> {
private Foo foo;
void setFoo(Foo foo) { this.foo = foo; }
@Override protected Task createTask() {
return new FooModifierTask(foo);
}
private class FooModifierTask extends Task<Foo> {
final private Foo fooInput;
FooModifierTask(Foo fooInput) { this.fooInput = fooInput; }
@Override protected Foo call() throws Exception {
Thread.currentThread().sleep(1000);
return new Foo(fooInput);
}
}
}
class Foo {
private final int answer;
Foo() { answer = random.nextInt(100); }
Foo(Foo input) { answer = input.getAnswer() + 42; }
public int getAnswer() { return answer; }
}
Service
在 Service javadoc中还有一个向 a 提供输入的示例。
要从服务返回自定义用户异常,只需在服务的任务调用处理程序期间抛出用户异常。例如:
class BadFooGenerator extends Service<Foo> {
@Override protected Task createTask() {
return new Task<Foo>() {
@Override protected Foo call() throws Exception {
Thread.currentThread().sleep(1000);
throw new BadFooException();
}
};
}
}
可以像这样检索异常:
BadFooGenerator badFooGenerator = new BadFooGenerator();
badFooGenerator.setOnFailed(new EventHandler<WorkerStateEvent>() {
@Override public void handle(WorkerStateEvent t) {
Throwable ouch = badFooGenerator.getException();
System.out.println(ouch.getClass().getName() + " -> " + ouch.getMessage());
}
});
badFooGenerator.start();
我创建了几个可执行示例,您可以使用它来尝试一下。