Java 8 parallel forEach progress indication - java

For performance reason I would like to use a forEach loop of a parallel Lambda stream in order to process an instance of a Collection in Java. As this runs in a background Service I would like to use the updateProgress(double,double) method in order to inform the user about the current progress.
In order to indicate the current progress I need a certain progress indicator in form of a Integer counter. However, this is not possible as I can only access final variables within the Lambda expression.
Code example see below, Collection is only a place holder for any possible instance of a Collection:
int progress = 0;
Collection.parallelStream().forEach(signer -> {
progress++;
updateProgress(progress, Collection.size());
});
I'm aware that I can solve this problem by using a simple for-loop. However, for performance reason it would nice to solve it in this way.
Does anybody know a more or less neat solution to this?

As proposed by markspace, using an AtomicInteger is a good solution:
AtomicInteger progress = new AtomicInteger();
Collection.parallelStream().forEach(signer -> {
progress.incrementAndGet();
// do some other useful work
});
I would not use the runLater() variant as your goal is a high performance, and if many parallel threads will generte JavaFX 'runLater' tasks, you will again create a bottleneck...
For the same reason I would NOT call an update to the ProgressBar each time, but use a seaparte JavaFX Timeline to update the progress bar in regular intervals independently from the processing threads.
Here is a full code comparing sequential and parallel processing with ProgressBar. If you remove the sleep(1) and set the number of items to 10 million it will still work concurrently and efficiently...
public class ParallelProgress extends Application {
static class ParallelProgressBar extends ProgressBar {
AtomicInteger myDoneCount = new AtomicInteger();
int myTotalCount;
Timeline myWhatcher = new Timeline(new KeyFrame(Duration.millis(10), e -> update()));
public void update() {
setProgress(1.0*myDoneCount.get()/myTotalCount);
if (myDoneCount.get() >= myTotalCount) {
myWhatcher.stop();
myTotalCount = 0;
}
}
public boolean isRunning() { return myTotalCount > 0; }
public void start(int totalCount) {
myDoneCount.set(0);
myTotalCount = totalCount;
setProgress(0.0);
myWhatcher.setCycleCount(Timeline.INDEFINITE);
myWhatcher.play();
}
public void add(int n) {
myDoneCount.addAndGet(n);
}
}
HBox testParallel(HBox box) {
ArrayList<String> myTexts = new ArrayList<String>();
for (int i = 1; i < 10000; i++) {
myTexts.add("At "+System.nanoTime()+" ns");
}
Button runp = new Button("parallel");
Button runs = new Button("sequential");
ParallelProgressBar progress = new ParallelProgressBar();
Label result = new Label("-");
runp.setOnAction(e -> {
if (progress.isRunning()) return;
result.setText("...");
progress.start(myTexts.size());
new Thread() {
public void run() {
long ms = System.currentTimeMillis();
myTexts.parallelStream().forEach(text -> {
progress.add(1);
try { Thread.sleep(1);} catch (Exception e1) { }
});
Platform.runLater(() -> result.setText(""+(System.currentTimeMillis()-ms)+" ms"));
}
}.start();
});
runs.setOnAction(e -> {
if (progress.isRunning()) return;
result.setText("...");
progress.start(myTexts.size());
new Thread() {
public void run() {
final long ms = System.currentTimeMillis();
myTexts.forEach(text -> {
progress.add(1);
try { Thread.sleep(1);} catch (Exception e1) { }
});
Platform.runLater(() -> result.setText(""+(System.currentTimeMillis()-ms)+" ms"));
}
}.start();
});
box.getChildren().addAll(runp, runs, progress, result);
return box;
}
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("ProgressBar's");
HBox box = new HBox();
Scene scene = new Scene(box,400,80,Color.WHITE);
primaryStage.setScene(scene);
testParallel(box);
primaryStage.show();
}
public static void main(String[] args) { launch(args); }
}

The naive solution would be to have progress as a field of some surrounding object; then referring to progress from a lambda closure would actually mean this.progress, where this is final, thus the compiler would not complain. However, the resulting code would access the progress field from multiple threads concurrently, which could cause race conditions. I suggest restricting access to the progress field to the JavaFX application thread, by using Platform.runLater. The whole solution then looks like this:
// accessed only on JavaFX application thread
private int progress = 0;
// invoked only on the JavaFX application thread
private void increaseProgress() {
progress++;
updateProgress(progress, collection.size());
}
private void processCollection() {
collection.parallelStream().forEach(signer -> {
// do the work (on any thread)
// ...
// when done, update progress on the JavaFX thread
Platfrom.runLater(this::increaseProgress);
});
}

Related

UI and background thread in JavaFX. bubble sort visualization

This is a bubble sort algorithm visualization code. I want rectangles to be swapped. However, I couldn't make it. When I run the program it waits a bit, max 2 seconds, then all rectangles are moving and it lasts 1 seconds or something. The problem is thread I guess, what should I do?
public void bubbleSort(Rectangle[] rectangles) throws InterruptedException {
int pass = 1;
for(int j = 0; j < rectangles.length-1; j++) {
for (int i = 0; i < rectangles.length - 1-j; i++) {
int pos = i;
if (rectangles[i].getHeight() > rectangles[i + 1].getHeight()) {
Runnable task = new Runnable() {
#Override
public void run() {
try {
System.out.println("opıjapısdjapsoıdj");
Platform.runLater(new Runnable() {
#Override
public void run() {
createAnimation(pos, pos + 1);
System.out.println("xxxxxxx");
}
});
Thread.sleep(2000);
} catch (InterruptedException exception) {
// nothing
}
}
};
new Thread(task).start();
Rectangle temp = rectangles[i];
rectangles[i] = rectangles[i + 1];
rectangles[i + 1] = temp;
}
}
}
}
Long running code should never be put on the JavaFX Application Thread, as this will cause your GUI to freeze and become unresponsive.
In simple situations, you can use:
Executors.newSingleThreadExecutor().execute(() -> doComputation());
to post a job to a different thread and:
Platform.runLater(() -> updateDisplay());
to post a GUI update to the Application Thread.
However, a more reccomended solution is to use a Service.
This is a class that you can extend, and provide a createTask() method, which you can then asynchronously call and listen for responses.
For example:
public class SortService extends Service<int[]> {
private int[] array;
public void sortArray(int[] array) {
this.array = array;
restart(); // restart() restarts the service regardless of its status
}
#Override
public Task<int[]> createTask() {
return new Task<int[]> {
#Override
protected int[] call() throws Exception {
// do your sorting and then return the result
return sortedArray;
}
}
}
}
Once you have this class setup, you can create an instance, set the array, and listen for results.
SortService service = new SortService();
service.valueProperty().addListener((obs, oldValue, newValue) -> {
// run on JavaFX Application Thread, safe to update GUI
System.out.println("Hello from JavaFX Application Thread");
System.out.println(Arrays.toString(newValue));
// newValue is our sorted int[] (it is the value you return in your service's createTask())
});
service.sortArray(Arrays.asList(1, 2, 5, 4, 3)); // launch the service
If you want to change the value during the running of your Service, before you return, you can call updateValue(newValue) (perhaps you want to display every stage of the sort instead of just the final output).

How do javafx multithreading execute sequentially?

I don't know if there are any other good ways to achieve the results I want, thank you.
I have a requirement, according to the URL, create multiple webview threads, and execute them in order, such as thread execution, then trigger thread two execution, and so on, I use the synchronized (lobject) method, but in JAVAfx encountered a problem, the code is as follows:
public class LockObject {
public int orderNum = 1;
public final static int MaxValue=9;
public LockObject(int orderNum){
this.orderNum = orderNum;
}
}
public class DownloadThread extends Thread{
private LockObject lobject;
private int printNum =0;
private String url;
public DownloadThread(LockObject lobject,int printNum,String url){
this.lobject=lobject;
this.printNum = printNum;
this.url = url;
}
#Override
public void run() {
synchronized(lobject){
while(lobject.orderNum <= lobject.MaxValue){
if(lobject.orderNum == printNum){
System.out.print(printNum);
Platform.runLater(new Runnable() {
#Override
public void run() {
webView.getEngine().load(url);
webView.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
#Override
public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) {
if (newValue == Worker.State.SUCCEEDED) {
try {
//xxxxx
// java.lang.IllegalMonitorStateException
lobject.notifyAll();
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
});
lobject.orderNum++;
if(lobject.orderNum==downloadThreads.length){
saveCsvFile(goodCSVS);
}
//lobject.notifyAll(); is ok
}else{
try {
lobject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
Place of call
private DownloadThread[] downloadThreads;
LockObject lobject = new LockObject(1);
downloadThreads = new DownloadThread[tableView.getItems().size()];
for (int i = 0; i < tableView.getItems().size(); i++) {
UrlModel item = tableView.getItems().get(i);
downloadThreads[i] = new DownloadThread(lobject,tableView.getItems().size()-i,item.getLink());
downloadThreads[i].start();
}
Calling lobject.notifyAll() in the run method in Platform.runLater will report an IllegalMonitorStateException. After the address is processed, I want to wake up the next thread to execute.
If you need to execute multiple tasks in order, there's no need to create multiple threads. Just using a single thread will guarantee the next task only executes after the previous one has completed. You should also consider using a CountDownLatch instead of synchronizing on an object.
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
for (UrlModel model : tableView.getItems()) {
executor.submit(() -> {
CountDownLatch latch = new CountDownLatch(1);
Platform.runLater(() -> {
engine.load(model.getLink())
engine.getLoadWorker().runningProperty().addListener((obs, ov, nv) -> {
if (!nv) {
latch.countDown();
}
});
});
latch.await();
// do whatever needs to happen after the WebEngine finishes loading
return null; // using #submit(Callable) and Callable needs to return something
});
}
} finally {
executor.shutdown();
}
Some notes:
You may want to avoid creating the ExecutorService if the table has no items to process. That is, assuming you don't reuse the same ExecutorService every time.
If you reuse the ExecutorService, don't call shutdown().
This ExecutorService uses non-daemon threads. You can customize this by supplying a ThreadFactory that creates daemon threads.
I added a listener to the Worker#running property instead of the status property to make it easier to ensure countDown() is invoked no matter the terminal status of the load (i.e. whether it's SUCCEEDED, CANCELLED or FAILED).
You may want to remove the the listener added to the Worker's property when it's finished. You can do this by using an anonymous class (rather than the lambda expression I used) and calling obs.removeListener(this) inside the changed method, where obs is the ObservableValue argument.

Fixing StackOverflowError recursivity using Runnable

I am getting StackOverflowError exception report while calling this recursive method :
private void downloadFiles(int index) {
if (index < totalFiles) {
downloadSingleFile(index, new DownloadCallback() {
#Override
public void onSuccess(String filePath) {
downloadFiles(index + 1);
}
});
}
}
I want to ask if I use a Runnable like this way:
int index = 0;
handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
downloadFiles();
}
};
handler.post(runnable);
private void downloadFiles() {
if (index < totalFiles) {
downloadSingleFile(index, new DownloadCallback() {
#Override
public void onSuccess(String filePath) {
index ++;
handler.post(runnable);
}
});
}
}
Will this be a recursivity as well and throw exception ?
Thanks
Your current use of recursion sort of defeats the purpose of using multiple threads. Currently, you only create a single thread which will enter downloadFiles(), and will then recursively try to download every file available. This is not really multithreading, it's single threading with recursion. There are several drawbacks to this approach. First, you are not taking advantage of the ability for multiple threads to do work in parallel. Second, since each subsequent recursive call is dependent on the previous one having succeeded, you are trying to download files in serial. If a given file download were to fail, it would break the rest of the recursive chain.
A better approach would be to spawn a new thread for each file download. This would allow you to use the power of multithreading to split the task in parallel, and it also allows progress to continue even if one thread were to encounter some problems.
Have a look at the following code snippet for an idea on how to approach your problem:
public class FileDownloader implements Runnable {
private index;
public FileDownloader(int index) {
this.index = index;
}
public void run() {
downloadSingleFile(index, new DownloadCallback() {
#Override
public void onSuccess(String filePath) {
// this may no longer be needed
}
});
}
}
// use a thread pool of size 5 to handle your file downloads
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int index=0; index < totalFiles; ++index) {
Runnable r = new FileDownloader(index);
executor.execute(r);
}
// shut down the thread pool executor and wait for it to terminate
executor.shutdown();
while (!executor.isTerminated()) {
}

Changelistener not triggered in Console but by GUI

I have a Task which should be runnable and updateable on Console and GUI. Consider my Task written as
public static Task<Void> doStuff() {
Task<Void> task;
task = new Task<Void>() {
final int totalSteps = 4;
#Override
public Void call() throws Exception {
updateProgress(0, totalSteps);
updateMessage("1");
action(1);
updateProgress(0, totalSteps);
updateMessage("2");
action(2);
//etc..
return null;
}
};
new Thread(task)
.start();
return task;
}
With bonding the Progress and Message Property within my JavaFX GUI, everything works as expected and the GUI gets updated according to the Progress.
Within my CLI, I tried to build a simple Progress Bar which updates the User about the Operation Progress
private static void progressBar(Task task) {
task.progressProperty().addListener((new ChangeListener() {
#Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
// Return to line beginning
System.out.print("\r");
int percentage = (int) (100 * task.progressProperty().get());
System.out.format("[%3d%%] %s", percentage, task.messageProperty().get());
if (percentage == 100) {
System.out.println("Finished");
}
}
}));
}
}
As far as I could see with debugging, the Change Listeners changed Method will not get triggered. What did I set up wrong about it? Even the Finished Print at the End will not get written.
As stated in the comments, updates to the properties in a JavaFX Task are performed on the FX Application Thread. That thread is the thread used to render the JavaFX Scene graph and is started by the JavaFX toolkit when it is launched. If the JavaFX toolkit is not running, then the thread won't be started and those properties will not be updated.
If you want something that can be run in a background that needs to be functional outside of a JavaFX application, then you should use threading facilities that are not dependent on JavaFX. In this case you can simply implement Runnable or Callable. If you want to provide notifications when state changes, create a callback, to be called when the state changes. Callbacks are best represented using interfaces from the java.util.function package.
In the case you show, it looks like you only really need the message and progress together, so you could probably use a BiConsumer<String, Integer>.
public class DoStuff implements Runnable {
private final int totalSteps ;
private BiConsumer<String, Integer> update ;
public DoStuff(int totalSteps) {
this.totalSteps = totalSteps ;
}
public void setUpdate(BiConsumer<String Integer> update) {
this.update = update ;
}
#Override
public void run() {
if (update != null) {
update.accept("0", 0) ;
}
for (int i = 1 ; i <= totalSteps ; i++) {
action(i);
if (update != null) {
update.accept(Integer.toString(i), i);
}
}
}
private void action(int i) {
// ...
}
public int getTotalSteps() {
return totalSteps() ;
}
}
and now you would do
public void progressBar(DoStuff doStuff) {
doStuff.setUpdate((s, p) -> {
// Return to line beginning
System.out.print("\r");
int percentage = 100 * p / doStuff.getTotalSteps();
System.out.format("[%3d%%] %s", percentage, s);
if (percentage == 100) {
System.out.println("Finished");
}
});
}
And you execute this in a background thread with
new Thread(doStuff).start();
If you wanted to use this in a JavaFX environment, you can, but make sure your callback updates any UI components on the FX Application Thread:
DoStuff doStuff = ... ;
doStuff.setUpdate((s, p) -> Platform.runLater(() -> {
label.setText(s);
double progress = 1.0 * p / doStuff.getTotalSteps();
progressBar.setProgress(p);
}));
It's also reasonably easy to create a Task<Void> that wraps this, and exposes the progress and message in the usual JavaFX way:
DoStuff doStuff = ... ;
Task<Void> doStuffTask = new Task<Void>() {
#Override
protected Void call() {
doStuff.setUpdate((s, p) -> {
updateProgress(p, doStuff.getTotalSteps());
updateMessage(s);
});
doStuff.run();
return null ;
}
};
Then do
progressBar.progressProperty().bind(doStuffTask.progressProperty());
label.textProperty().bind(doStuffTask.messageProperty());
Thread t = new Thread(doStuffTask);
t.setDaemon(true);
t.start();
as usual.

JavaFX Multithreading

I am facing one problem in my JavaFx application.
Preface: I don't want to be specific to my application only but want to be generalized so that people like me will get an idea on similar situation.
Background: Implementing a Javafx application using fxml file and multi-threading concept.
Summary: I tried make an application which basically uses multi threading to do some task, and once multi- threading is completed, it will sequentially move to another task. While doing the multi-threading the Main GUI freezes.
What I did,
//This is Main class
Parent Root -> defined on top
public Parent createContent(){
try{
root = FXMLLoader.load(getClass().getResource("Layout.fxml"));
}catch { .....}
}
public void start(){
stage.setScene(new Scene(createContent()));
Task<Void> task = new Task<Void>() {
#Override
public Void call() throws Exception {
Thread.sleep(1000);
return null ;
}
};
task.setOnSucceeded(event->{
stage.show();
});
new Thread(task).run();
}
public static void main(String[] args) {
launch(args);
}
// This is inside the controller on button click event
#FXML
private void start(ActionEvent event) { <---- This one is button click event
Thread t1 = new Thread(new Mul());
t1.start();
Thread t2 = new Thread (new Mul());
t2.start();
}
// Finally
public class Mul implements Runnable {
public void type() {
for (int a = 0; a < 200000; a++) {
System.out.println( Thread.currentThread().getName()+ " says " + a);
}
}
#Override
public void run() {
type();
}
}
Now, here is the outcome.
If I just start the threads from the controller then My main application does not freezes while the thread are running in background. However, since the application runs in a sequence, i.e the next step only works when the threads complete their work
I can use t1.join() and t2.join() , but doing so will freezes my main application(Main application here is the main GUI) and I cannot proceed with it until the threads are completed.
What could be the optimal solution, so that I can use multi threading without blocking the main application or What am I doing wrong here? (info, I came to this solution by following up different suggestions from Stack overflow and google)
Why not do
Task<Void> task = new Task<Void>() {
#Override
public Void call() {
Mul m1 = new Mul();
m1.run();
Mul m2 = new Mul();
m2.run();
return null ;
}
};
new Thread(task).start();
If you really want to "chain" different tasks, call one from the other's onSucceeded handler:
Task<Void> task1 = new Task<Void>() {
#Override
public Void call() {
new Mul().run();
return null ;
}
};
Task <Void> task2 = new Task<Void>() {
#Override
public Void call() {
new Mul().run();
return null ;
}
};
task1.setOnSucceeded(e -> new Thread(task2).start());
new Thread(task1).start();
Obviously this is cleaner if you make Mul a Task subclass instead of a Runnable, and it's better to use an Executor with daemon threads, etc, but this should give you the idea.

Categories