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).
Related
I have a task that compress an image, which use many many loops inside it:
private void writeCompressedData() {
int i, j, r, c, a, b;
loat[][] inputArray;
for (r = 0; r < minBlockHeight; r++) {
for (c = 0; c < minBlockWidth; c++) {
xpos = c * 8;
pos = r * 8;
for (comp = 0; comp < jpegObj.numberOfComponents; comp++) {
inputArray = (float[][]) jpegObj.components[comp];
for (i = 0; i < jpegObj.VsampFactor[comp]; i++) {
for (j = 0; j < jpegObj.HsampFactor[comp]; j++) {
xblockoffset = j * 8;
yblockoffset = i * 8;
for (a = 0; a < 8; a++) {
for (b = 0; b < 8; b++) {
// Process some data and put to inputArray
}
}
// Encode Huffman block
}
}
}
}
}
}
I run this method inside a normal thread like this:
new Thread(new Runnable() {
#Override
public void run() {
writeCompressedData();
}
});
Or run inside a background worker thread
TaskExecutor.queueRunnable(new Runnable() {
#Override
public void run() {
writeCompressedData();
}
});
The problem is: this method sometimes go wrong and cause infinite loops when receive invalid input. In that case, it will run forever and hurt the CPU even when the device's screen turn off which increase device's temperature (and if I use worker thread it also blocks other tasks inside waiting queue).
I think I need to set a timeout to terminate long running task. What's the best way to achieve this in normal Java thread? Does RxJava support it?
I know what I need to fix is the "wrong" method, not just terminate it. But for the big apps, it's hard to control other developer's code, and the first thing I need is avoid affecting users.
You'd need some form of cooperative cancellation, say checking Thread.currentThread().isInterrupted() inside one or more of the nested loops.
for (/* ... */) {
if (Thread.currentThread().isInterrupted()) return;
for (/* ... */) {
if (Thread.currentThread().isInterrupted()) return;
for (/* ... */) {
// the tightest loop
}
}
}
Then when you run the method, keep the Thread/Future and call interrupt/cancel(true):
backgroundTask = new Thread(() -> method());
backgroundTask.start();
// ...
backgroundTask.interrupt();
backgroundFuture = executorService.submit(() -> method());
// ...
backgroundFuture.cancel(true);
In RxJava this would look something like this:
backgroundDisposable = Completable.fromAction(() -> method())
.subscribeOn(Schedulers.io()) // dedicated thread recommended
.observeOn(AndroidSchedulers.mainThread())
.subscribe(() -> { /* done */ }, e -> { /* error */ });
// ...
backgroundDisposable.dispose();
You could use Java ExecutorService with timeout and Future to fix this problem. See this post.
A better way is to run such code in different process. Even the process crashed the main process will be un-impacted.
My Approach is with using RxJava and more specifically using Timeout operator of RxJava, Here is the gist of the code, After 5 seconds the onError will be called as there is no emission of an item within the previous 5 seconds,
private void timeOutObserver() {
Observable.create(new ObservableOnSubscribe<String>() {
#Override
public void subscribe(ObservableEmitter<String> emitter) {
emitter.onNext("A");
}
})
.timeout(5000, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
#Override
public void onSubscribe(Disposable d) {
Log.d("-#-", "subscribed");
}
#Override
public void onNext(String s) {
Log.d("-#-", "on next " + s);
}
#Override
public void onError(Throwable e) {
Log.d("-#-", e.getLocalizedMessage());
}
#Override
public void onComplete() {
Log.d("-#-", "on complete");
}
});
}
For more working on TimeOut operator refer this,
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()) {
}
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.
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);
});
}
Let's say that I have an algorithm that does something for a given parameter. If the algorithm runs longer than 100 miliseconds then I want to stop it and try again for a different parameter.
I posted below the code that would test the algorithm for a random parameter... and how I think the code might look like:
public class StopThread {
private Lock lock = new ReentrantLock();
public static void main(String... args) {
System.out.println("Starting threads...");
(new StopThread()).startThreads(100);
}
private void startThreads(int nrOfThreads) {
for (int i = 0; i < nrOfThreads; i++) {
startThread(i, (long) (Math.random() * 10000000000l));
System.out.println("Started thread number " + (i + 1));
}
}
private void startThread(final int number, final long load) {
Thread workerThread = new Thread() {
#Override
public void run() {
try {
lock.lock();
doAlgorithmWork(load);
} finally {
System.out.println("Thread " + (number + 1) + " finished...");
lock.unlock();
}
}
};
Thread timerThread = new Thread() {
#Override
public void run() {
try {
sleep(100);
} catch (InterruptedException e) {
}
}
};
workerThread.start();
timerThread.start();
do {
if (!workerThread.isAlive() || !timerThread.isAlive()) {
workerThread.stop();
timerThread.stop();
}
} while (!workerThread.isAlive() && !timerThread.isAlive());
}
protected void doAlgorithmWork(long load) {
while (load-- > 0) {
}
}
}
I feel like this question should already have an answer, but what I found until now seemed complicated and I didn't know how to use it. I'm not that knowledgeable with threads and I would appreciate if you could post some code.
A very simple solution would look like this:
private void startThreads(int nrOfThreads) {
for (int i = 0; i < nrOfThreads; i++) {
Thread worker = new Thread() {
#Override
public void run() {
doAlgorithmWork((long) (Math.random() * 10000000000l));
}
}
worker.start();
worker.join(100); //block until either the thread is done, or 100ms passed
if (worker.isAlive()) worker.stop(); //if thread is still alive, stop it
}
}
This will achieve your goal, but suffers from a number of "drawbacks"
It is single threaded (that is, all calls to doAlgorithm execute one after another, instead of in parallel, so you are only using a single core of your machine);
It uses the discouraged Thread.stop() method. A preferred approach is to instead have a "stop" flag which is set to true (in place of the stop() call), and which is also constantly checked for in doAlgorith;
It creates a new thread for each doAlgorithm call (instead of reusing a single thread), which is "wasteful", but for your case probably has little practical implications
UPDATE:
In order to avoid the deprecated stop() call, you will need to add a flag to your worker thread, creating a separate class like this:
public class Worker implements Runnable {
private volatile boolean stopped = false;
public void stop() {
stopped = true;
}
#Override
public void run() {
doAlgorithmWork((long) (Math.random() * 10000000000l));
}
private void doAlgorithmWork(long load) {
while (!stopped && load-- > 0) {
//calculation
}
}
}
Then your runner looks like this:
private void startThreads(int nrOfThreads) {
for (int i = 0; i < nrOfThreads; i++) {
Thread worker = new Thread(new Worker());
worker.start();
worker.join(100); //block until either the thread is done, or 100ms passed
if (worker.isAlive()) worker.stop(); //if thread is still alive, stop it
}
}
You could also create a constructor for Worker which accepts the load value (instead of having it generated inside the Worker itself).
Note that if the calculation inside doAlgorithm() is too time-consuming, the thread may run for more than 100ms (since it always completes each calculation within the loop). If this is an issue, then your alternative is to interrupt the thread instead (calling worker.interrupt() will cause an InterruptedException to be thrown within the run() method).