Stop current running thread with certain condition, with finally block being called - java

I have a method which is long and has many inner loops, at some point in the inner loop if a certain condition is met, I want the thread to be terminated but I also want the finally block to be called so clean up also happens. How can I do this?

Call return; when you want to stop. That will leave the loop and run the finally (so long as the loop with the return statement is within the try block).
E.g.
pseudocode:
public void run () {
try {
loop {
loop {
if (condition) return;
}
}
} finally {
// always run
}
}

Remember that "terminating the thread" really just means-- or should mean!-- that the run() method exits. Put the finally outside the loop, as the last thing in the thread's/Runnable's run() method.

Related

Why shutdownNow() method is able to break for-loop inside Callable object, but fails to do so inside Runnable, unless we specifically call break?

I have this code snippet that runs a single thread executor with two tasks of either Callable, or Runnable type. Both tasks run a simple for-loop counter with Thread.sleep() delay per iteration. The second task starts off immediately after the first task is finished. The awaitTermination() method is supposed to shutdown executor before it manages to complete.
I understand that shutdownNow() calls interrupt() to a currently executing task as soon as time elapses in awaitTermination(), somehow managing to immediately break the for-loop inside the first task and aborting the second task if the type of object is MyCallableTask. Now, if I change the type of submitted objects to MyRunnableTask the code will also terminate the for-loop as expected, but only because I've included break in the try-catch block when calling Thread.sleep().
#Override public void run() {
for (int j = 0; j < forLoops; j++) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
break;
}
}
}
If there was no break, the code would have finished the for-loop first and then stop.
My question is why don't we need to include any breaks or returns in call() implementation of MyCallableTask? I mean, how come the code succeeds to immediately break the for-loop in the call() method without any additional instructions?
#Override public Void call() throws Exception {
for (int j = 0; j < forLoops; j++) {
Thread.sleep(sleepTime);
}
return null;
}
InterruptedException is a checked exception.
You either have to handle it inside the method (with a try/catch), or declare that the method throws it (or a superclass).
Runnable implementations can't throw checked exceptions like InterruptedException (its base declaration doesn't have throws Exception or throws InterruptedException); Callable can, because its declaration does.
Btw, your Runnable case should call Thread.currentThread().interrupt() before the break, so that anything which called that Runnable can also know it was interrupted.
You also don't really need the break of you put the try/catch around the loop instead of inside it.

Safe stop thread

I have some class:
#Component
public MyClass {
private volatile boolean stopped = false;
public void verification() throws Exception {
Thread kpiAllThread = getKPIAllThread();
try {
for (int i = 0; i < poolSize; i++) {
execDispatcher.put(processExecutor.submit(getCheckValuesInKPIConsumerTask(workingQueue)));
}
kpiAllThread.start();
} finally {
waitFinished();
}
}
public void setStop(bolean stopped) {
this.stopped = stopped;
}
private Thread getKPIAllThread() {
return new Thread(() -> {
try {
LOG.debug("KPIAllThread started!");
dao.getKpiAll(workingQueue);
for (int i = 0; i < poolSize; i++) {
workingQueue.put(() -> true);
}
} catch (Exception ex) {
LOG.error("KPIAllThread exception: ", ex);
} finally {
LOG.error("KPIAllThread finished!");
}
});
}
}
This class starts the producer thread getKPIAllThread. He get data from db and put in BlockingQueue.
Method getKpiAll like this:
public void getKpiAll(final BlockingQueue<KeyPropertyIndex> kpiData) throws Exception {
LOG.debug("Starting getKpiAll");
try (final Connection con = dataSource.getConnection();
final Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) {
stmt.setFetchSize(Integer.MIN_VALUE);
try (final ResultSet rs = stmt.executeQuery(sqlGetAllkpi)) {
while (rs.next()) {
kpiData.put(new KeyPropertyIndexData(rs.getLong(1), rs.getString(2)));
}
}
LOG.debug("Finished get getKpiAll");
} catch (Exception ex) {
throw ex;
}
}
There is also a variable stopped that can be set from outside to true. How can I safely stop my thread while doing so? So that all connections to the database are closed and the thread is successfully completed?
The cleanest and safest rule for stopping a thread is that the code running in thread should periodically check a condition (say, boolean shouldExit()). When the code detects that this condition is true, it should stop doing what is doing and terminate.
The code running in thread should check this condition fairly often so that it can react reasonably fast. As a rule of thumb, the thread should exit less than one second after you set this condition. The check would typically look something like if (shouldExit()) break somewhere in your for-loop that iterates over pool size. However, dao.getKpiAll(workingQueue) looks potentially long, so you might place more checks inside getKpiAll.
When you have this checking in place, you must ensure that your code will exit cleanly every time the condition becomes true. For example, you can use finally blocks to close any connections etc. If this happens during getKpiAll, there is no sense to even continue with for loop to process items and so on.
Sometimes, this can get more tricky - i.e. when the thread is waiting on a network operation, you might need to close the network socket or something like that to interrupt it. In any case, avoid using Thread.stop() or Thread.interrupt() - see documentation why they are problematic.
If you do things like this, you can set the condition from outside the thread at any time to request the thread to terminate. You can make something like void requestExit() and set a boolean variable there. After calling requestExit(), you call Thread.join() with a suitable timeout to wait for the thread to do its business, check the condition and exit. Again, as a rule of thumb, make the timeout 3-10 times as long as the longest reaction time of your thread.
It looks that you already have setStopped(boolean stopped) for that purpose, but you're not checking it. First, I would remove parameter stopped because it doesn't make sense to pass false to it. Second, you need to add checks as described above. You might want to make this variable visible to dao - just remember that it's much better to expose it as a synchronized boolean method than as a boolean field.

Break while loop immediately when condition is false

Is there a possibility to break a while-loop immediately after the condition gets false?
while(true){
//Backgroundtask is handling appIsRunning boolean
while (appIsRunning) {
Roboter.movement1(); //while Roboter.movement1 is running appIsRunning changes to false
Roboter.movement2();
}
while (!appIsRunning) {
//wait for hardbutton/backgroundtask to set appIsRunning true
}
}
I don't want to wait until the first movement is done, the while should break immediatelty and closes the Roboter.class.
And I dont want to check inside the Roboter.class if appIsRunning is true...
If you want to completele stop Roboter.movement1() execution immideatly, you should use another thread and execute it there:
Thread mover = new Thread() {
#Override
public void run() {
Roboter.movement1();
}
}
mover.start();
and when you need to stop, use mover.stop();
Carefull: using stop() may cause wrong behaviour of your program
How do you kill a thread in Java?
Cleanest way to do it without re-thinking your "architecture" (which I would suggest, but depends on what you're trying to achieve would be to do:
while(true){
while (appIsRunning) {
if(!Roboter.movement1()) { //Hardbutton is pressed to stop application / appIsRunning is false
break;
}
Roboter.movement2();
}
while (!appIsRunning) {
//wait for hardbutton/backgroundtask to set appIsRunning true
}
}
And returning false from "movement1()" when you want to leave...
type break; where the condition fails! simple!

Stop executing further code in Java

I have looked in the Javadoc but couldn't find information related to this.
I want the application to stop executing a method if code in that method tells it to do so.
If that sentence was confusing, here's what I want to do in my code:
public void onClick(){
if(condition == true){
stopMethod(); //madeup code
}
string.setText("This string should not change if condition = true");
}
So if the boolean condition is true, the method onClick has to stop executing further code.
This is just an example. There are other ways for me to do what I am trying to accomplish in my application, but if this is possible, it would definitely help.
Just do:
public void onClick() {
if(condition == true) {
return;
}
string.setText("This string should not change if condition = true");
}
It's redundant to write if(condition == true), just write if(condition) (This way, for example, you'll not write = by mistake).
return to come out of the method execution, break to come out of a loop execution and continue to skip the rest of the current loop. In your case, just return, but if you are in a for loop, for example, do break to stop the loop or continue to skip to next step in the loop
To stop executing java code just use this command:
System.exit(1);
After this command java stops immediately!
for example:
int i = 5;
if (i == 5) {
System.out.println("All is fine...java programm executes without problem");
} else {
System.out.println("ERROR occured :::: java programm has stopped!!!");
System.exit(1);
}
There are two way to stop current method/process :
Throwing Exception.
returnning the value even if it is void method.
Option : you can also kill the current thread to stop it.
For example :
public void onClick(){
if(condition == true){
return;
<or>
throw new YourException();
}
string.setText("This string should not change if condition = true");
}
You can just use return to end the method's execution
Either return; from the method early, or throw an exception.
There is no other way to prevent further code from being executed short of exiting the process completely.
I think just using return; would do the job

Stopping thread Immediately

I want to stop a running thread immediately. Here is my code:
Class A :
public class A() {
public void methodA() {
For (int n=0;n<100;n++) {
//Do something recursive
}
//Another for-loop here
//A resursive method here
//Another for-loop here
finishingMethod();
}
}
Class B:
public class B() {
public void runEverything() {
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
A a = new A();
a.methodA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
My problem is that i need to be able to stop the thread in Class B even before the thread is finished. I've tried interrupt() method, but that doesn't stop my thread. I've also heard about using shared variable as a signal to stop my thread, but I think with long recursive and for-loop in my process, shared-variable will not be effective.
Any idea ?
Thanks in advance.
Thread.interrupt will not stop your thread (unless it is in the sleep, in which case the InterruptedException will be thrown). Interrupting basically sends a message to the thread indicating it has been interrupted but it doesn't cause a thread to stop immediately.
When you have long looping operations, using a flag to check if the thread has been cancelled is a standard approach. Your methodA can be modified to add that flag, so something like:
// this is a new instance variable in `A`
private volatile boolean cancelled = false;
// this is part of your methodA
for (int n=0;n<100;n++) {
if ( cancelled ) {
return; // or handle this however you want
}
}
// each of your other loops should work the same way
Then a cancel method can be added to set that flag
public void cancel() {
cancelled = true;
}
Then if someone calls runEverything on B, B can then just call cancel on A (you will have to extract the A variable so B has a reference to it even after runEverything is called.
I think you should persevere with using Thread.interrupt(). But what you need to do to make it work is to change the methodA code to do something like this:
public void methodA() throws InterruptedException {
for (int n=0; n < 100; n++) {
if (Thread.interrupted) {
throw new InterruptedException();
}
//Do something recursive
}
// and so on.
}
This is equivalent declaring and using your own "kill switch" variable, except that:
many synchronization APIs, and some I/O APIs pay attention to the interrupted state, and
a well-behaved 3rd-party library will pay attention to the interrupted state.
Now it is true that a lot of code out there mishandles InterruptedException; e.g. by squashing it. (The correct way to deal with an InterruptedException is to either to allow it to propagate, or call Thread.interrupt() to set the flag again.) However, the flip side is that that same code would not be aware of your kill switch. So you've got a problem either way.
You can check the status of the run flag as part of the looping or recursion. If there's a kill signal (i.e. run flag is set false), just return (after whatever cleanup you need to do).
There are some other possible approaches:
1) Don't stop it - signal it to stop with the Interrupted flag, set its priority to lowest possible and 'orphan' the thread and any data objects it is working on. If you need the operation that is performed by this thread again, make another one.
2) Null out, corrupt, rename, close or otherwise destroy the data it is working on to force the thread to segfault/AV or except in some other way. The thread can catch the throw and check the Interrupted flag.
No guarantees, sold as seen...
From main thread letsvsay someTask() is called and t1.interrput is being called..
t1.interrupt();
}
private static Runnable someTask(){
return ()->{
while(running){
try {
if(Thread.interrupted()){
throw new InterruptedException( );
}
// System.out.println(i + " the current thread is "+Thread.currentThread().getName());
// Thread.sleep( 2000 );
} catch (Exception e) {
System.out.println(" the thread is interrputed "+Thread.currentThread().getName());
e.printStackTrace();
break;
}
}
o/P:
java.lang.InterruptedException
at com.barcap.test.Threading.interrupt.ThreadT2Interrupt.lambda$someTask$0(ThreadT2Interrupt.java:32)
at java.lang.Thread.run(Thread.java:748)
the thread is interrputed Thread-0
Only t1.interuuption will not be enough .this need check the status of Thread.interrupted() in child thread.

Categories