Terminate long running task inside background thread - java

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,

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).

Synchronization simplification

I'm currently working on threading and synchronization.
I'm trying to print "A" 2 times, "B" 1 time, and "C" 4 times with this program, which basically works but I was wondering if there is a smaller and simpler solution to this, like putting all the classes into one or something similar.
Here is the code.
public class foo {
public static int countA = 0;
public static int countB = 0;
public static int countC = 0;
public static void main(String[] args) {
AThread athread = new AThread(new AClass());
BThread bthread = new BThread(new BClass());
CThread cthread = new CThread(new CClass());
athread.start();
bthread.start();
cthread.start();
}
static class AClass {
public synchronized void printA() throws InterruptedException {
if(countA == 2)
wait();
for(int i=1; i<3; i++) {
System.out.println("A"+i);
countA++;
}
}
}
static class BClass{
public synchronized void printB() throws InterruptedException {
if(countB == 1)
wait();
for(int i=1; i<2; i++) {
System.out.println("B"+i);
countB++;
}
}
}
static class CClass{
public synchronized void printC() throws InterruptedException {
if(countC == 4)
wait();
for(int i=1; i<5; i++) {
System.out.println("C"+i);
countC++;
}
}
}
static class AThread extends Thread {
AClass A = new AClass();
AThread(AClass a){
this.A = a;
}
public void run() {
try {
A.printA();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
static class BThread extends Thread {
BClass B = new BClass();
BThread(BClass b){
this.B = b;
}
public void run() {
try {
B.printB();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
static class CThread extends Thread {
CClass C = new CClass();
CThread(CClass c){
this.C = c;
}
public void run() {
try {
C.printC();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Even though the task does not require threads, here is a different way of writing the code in the description using java 8 CompletableFuture
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
for (int i = 0; i < 2; i++) {
System.out.println("A" + (i + 1));
}
}).thenRunAsync(() -> {
System.out.println("B1");
}).thenRunAsync(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("C" + (i + 1));
}
});
As the first comment says, there is no synchronization at all going on between any of your objects. Perhaps this might become apparent by changing the order in which you start the threads (C first, then B, then A).
For scheduling between Threads to work, you need to :
find an object that is visible to both threads so that both can wait() and notify() on that object.
establish the condition that will cause the waiting to stop and put that in a while()
so you get sort of :
while (countA < 2) AClass.class.wait();
in the B thread (and catch the InterruptedException in the loop, don't propagate)
and in the A thread you put
AClass.class.notify();
after the print loop has exited.
You can (and in industrial settings mostly should) replace AClass.class with a synchronisation object dedicated to the purpose (and which has been made visible to both threads).
The while() is necessary because of what is known as "spurious wakeups" : a wait() will exit if a notify() has caused it to do so, but it can also exit without such a notify() having been issued.
And finally, note that the condition in the while() loop accesses countA field from thread B, while thread A might be updating it. With simple integers this may still be failproof, but with more complex evaluations this is in itself a potential source of race condition errors so those accesses need to be synchronized in turn. Also note that while(countA<2) might never become true if thread A crashes for whatever reason so this is not the most robust way of setting things up as it will cause system hangs.
If all this is more like gibberish than English, you should first try and find a decent tutorial on threading and study that carefully.

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.

Java 8 parallel forEach progress indication

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);
});
}

Stop an algorithm in a thread after a given time has passed

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).

Categories