JavaFX的同步机制(二)
reak;
}
updateMessage("Iteration " + iterations);
updateProgress(iterations, 1000);
//短时锁定线程,但要保证对取消进行InterruptedException 检查
try {
Thread.sleep(100);
} catch (InterruptedException interrupted) {
if (isCancelled()) {
updateMessage("Cancelled");
break;
}
}
}
return iterations;
}
};
后台Task的完成进度
多线程程序中一个典型的用例是获取后台任务的完成情况。假设有一个后台任务对1到100000进行计数,并且要在进度条中对后台任务的完成情况进行更新。例3展示了如何更新一个进度条。
例3:
[java]
import javafx.concurrent.Task;
Task task = new Task() {
@Override public Void call() {
static final int max = 1000000;
for (int i=1; i<=max; i++) {
if (isCancelled()) {
break;
}
updateProgress(i, max);
}
return null;
}
};
ProgressBar bar = new ProgressBar();
bar.progressProperty().bind(task.progressProperty());
new Thread(task).start();
首先,通过重写call方法创建一个任务,并在方法体内实现业务逻辑,然后调用updateProgress方法来更新任务的progress、totalWork和workDone属性。很重要的一点是,现在可以使用progressProperty方法来处理任务的进度,并将任务进度与进度件的进度绑定在一起。
Service类
Service类设计用于在一个或多个后台线程中执行Task对象。Service类的方法和状态只能在JavaFX应用程序线程中进行访问。这个类的设计意图是帮助开发者在后台线程和JavaFX应用程序线程间正确地实现交互。
对Service对象可以进行如下控制:启动、取消、根据需要重启。要启动Service对象,使用Service.start()方法。
使用Service类,可以观察后台工作的状态并取消它。然后,还可以重置并重启,服务可以声明方式定义并根据需要重启。
实现Service类的子类时,要保证向Task对象暴露作为子类属性的输入参数。
服务可以以下方式执行:
通过Executor对象,如果它被指定作为给定服务的执行器。
如果没有指定执行器,通过守护线程启动。
通过自定义的执行器,比如ThreadPoolExecutor。
例4展示了一个Service类的实现,它读取并返回一个URL的第一行。
例4:
[java]
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
public class FirstLineServiceApp extends Application {
@Override
public void start(Stage stage) throws Exception {
FirstLineService service = new FirstLineService();
service.setUrl("http://google.com");
service.setOnSucceeded(new EventHandler() {
@Override
public void handle(WorkerStateEvent t) {
System.out.println("done:" + t.getSource().getValue());
}
});
service.start();
}
public static void main(String[] args) {
launch();
}
private static class FirstLineService extends Service {
private StringProperty url = new SimpleStringProperty();
public final void setUrl(String value) {
url.set(value);
}
public final String getUrl() {
return url.get();
}
public final StringProperty urlProperty() {
return url;
}
protected Task createTask() {
final String _url = getUrl();