Skip to content

Instantly share code, notes, and snippets.

@jewelsea
Created February 13, 2013 20:29
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jewelsea/4947946 to your computer and use it in GitHub Desktop.
Save jewelsea/4947946 to your computer and use it in GitHub Desktop.
JavaFX service examples for executing service tasks in parallel or sequentially.
import java.io.*;
import java.net.URL;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.concurrent.*;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class FirstLineSequentialVsParallelService extends Application {
private static final String[] URLs = {
"http://www.google.com",
"http://www.yahoo.com",
"http://www.microsoft.com",
"http://www.oracle.com"
};
private ExecutorService sequentialFirstLineExecutor;
private ExecutorService parallelFirstLineExecutor;
@Override public void init() throws Exception {
sequentialFirstLineExecutor = Executors.newFixedThreadPool(
1,
new FirstLineThreadFactory("sequential")
);
parallelFirstLineExecutor = Executors.newFixedThreadPool(
URLs.length,
new FirstLineThreadFactory("parallel")
);
}
@Override
public void stop() throws Exception {
parallelFirstLineExecutor.shutdown();
parallelFirstLineExecutor.awaitTermination(3, TimeUnit.SECONDS);
sequentialFirstLineExecutor.shutdown();
sequentialFirstLineExecutor.awaitTermination(3, TimeUnit.SECONDS);
}
public static void main(String[] args) { launch(args); }
@Override public void start(Stage stage) throws Exception {
final VBox messages = new VBox();
messages.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
messages.getChildren().addAll(
new Label("Parallel Execution"),
new Label("------------------"),
new Label()
);
fetchFirstLines(messages, parallelFirstLineExecutor);
messages.getChildren().addAll(
new Label("Sequential Execution"),
new Label("--------------------"),
new Label()
);
fetchFirstLines(messages, sequentialFirstLineExecutor);
messages.setStyle("-fx-font-family: monospace");
stage.setScene(new Scene(messages, 600, 800));
stage.show();
}
private void fetchFirstLines(final VBox monitoredLabels, ExecutorService executorService) {
for (final String url: URLs) {
final FirstLineService service = new FirstLineService();
service.setExecutor(executorService);
service.setUrl(url);
final ProgressMonitoredLabel monitoredLabel = new ProgressMonitoredLabel(url);
monitoredLabels.getChildren().add(monitoredLabel);
monitoredLabel.progress.progressProperty().bind(service.progressProperty());
service.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override public void handle(WorkerStateEvent t) {
monitoredLabel.addStrings(
service.getMessage(),
service.getValue()
);
}
});
service.start();
}
}
public class ProgressMonitoredLabel extends HBox {
final ProgressBar progress;
final VBox labels;
public ProgressMonitoredLabel(String initialString) {
super(20);
progress = new ProgressBar();
labels = new VBox();
labels.getChildren().addAll(new Label(initialString), new Label());
progress.setPrefWidth(100);
progress.setMinWidth(ProgressBar.USE_PREF_SIZE);
HBox.setHgrow(labels, Priority.ALWAYS);
setMinHeight(80);
getChildren().addAll(progress, labels);
}
public void addStrings(String... strings) {
for (String string: strings) {
labels.getChildren().add(
labels.getChildren().size() - 1,
new Label(string)
);
}
}
}
public static class FirstLineService extends Service<String> {
private StringProperty url = new SimpleStringProperty(this, "url");
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();
return new Task<String>() {
protected String call() throws Exception {
updateMessage("Called on thread: " + Thread.currentThread().getName());
URL u = new URL(_url);
BufferedReader in = new BufferedReader(
new InputStreamReader(u.openStream()));
String result = in.readLine();
in.close();
// pause just so that it really takes some time to run the task
// so that parallel execution behaviour can be observed.
for (int i = 0; i < 100; i++) {
updateProgress(i, 100);
Thread.sleep(50);
}
return result;
}
};
}
}
static class FirstLineThreadFactory implements ThreadFactory {
static final AtomicInteger poolNumber = new AtomicInteger(1);
private final String type;
public FirstLineThreadFactory(String type) {
this.type = type;
}
@Override public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable, "LineService-" + poolNumber.getAndIncrement() + "-thread-" + type);
thread.setDaemon(true);
return thread;
}
}
}
@jewelsea
Copy link
Author

Answer to Oracle JavaFX forum question: Creating multiple parallel tasks by a single service

@jewelsea
Copy link
Author

Also related to StackOverflow question: How to reset progress indicator between tasks in JavaFX2?

@aditsu
Copy link

aditsu commented Apr 23, 2016

Hi, why are you using multiple Services rather than just multiple Tasks?

@omernaci
Copy link

Hi 'John';

First of all I apologize for asking the question under this heading, I tried to reach you directly, but I could not access your mail.

https://community.oracle.com/message/14486835#14486835 as I explained under the title, I want to use progress when loading a new scene.

How can I do this, share your suggestions, Could you come back if you are available ?

Best Regards,
omernaci

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment