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.
Related
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.
I have a following scenario. Several threads are waiting on the same condition. And when are notified, all should stop waiting, change flag and return object:
public Object getObject(){
lock.lock();
try {
while (check)){
condition.await();
}
return returnObjectAndSetCheckToFalse();
} finally {
lock.unlock();
}
}
however this code does not work, since faster thread could change check flag to false, and second slower thread will block again.
It is possible to have a logic that both waiting threads will be awaken, they both will set check flag to false, and return object?
Or maybe it is contradictory?
The easiest way would be to change wait to if statement, however this would be vulnerable to spurious wakeup.
You could use CountDownLatch or a CyclicBarrier.
Using a Future is also a possibility, a FutureTask to be more specific. It has a conveniance method get() which can be used to block code execution until the Future has completed its job, thus fulfilling your requirements.
You could also implement your own Barrier which would do wait() in a loop until a certain condition has been met. Fulfilling that condition would trigger notifyAll(), loop would finish and all threads could continue. But that would be reinventing the wheel.
As I understand you need to return from the method body in all threads if your condition.await() returns.
This ugly solution should help although I think there's a better way to solve this:
public Object getObject() {
lock.lock();
try {
int localstate = this.state;
while (check && localstate == this.state)) {
condition.await(); // all threads that are waiting here have the same state
}
if (!check) {
this.state++; // first thread will change state thus making other threads ignore the 'check' value
}
return returnObjectAndSetCheckToFalse();
} finally {
lock.unlock();
}
}
What I think is you're trying to achieve, done using Futures:
ExecutorService executor = Executors.newCachedThreadPool();
// producer
final Future<String> producer = executor.submit(new Callable<String>() {
#Override
public String call() throws Exception {
Thread.sleep(5000);
return "done";
}
});
// consumers
for (int i = 0; i < 3; i++) {
final int _i = i;
executor.submit(new Runnable() {
#Override
public void run() {
System.out.println("Consumer "+_i+" starts.");
try {
String value = producer.get();
System.out.println("Consumer "+_i+" ends: "+value);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
If you run this, you should see all the consumer threads printing out their starting message, then a pause, then the consumer threads print out they're done. Obviously you'd have to change whatever is producing the value of getObject() into a Callable but I'd bet good money this will simplify the code since now it'll be structured procedurally instead of storing the result of a computation in a shared variable. I'm also more confident it's thread safe than of any code using manual locking.
One way of doing it is using wait() instead of condition.await(). Then use notifyAll() to wake up the threads.
Ideally, you would continue using the condition object that causes the thread to sleep and invoke the method signalAll() to wake up all the threads.
In you code I would just add:
public Object getObject(){
lock.lock();
try {
while (check)){
condition.await();
}
condition.signalAll();
return returnObjectAndSetCheckToFalse();
} finally {
lock.unlock();
}
}
I would even look at the possibility of using the condition.signalAll() inside the returnObjectAndSetCheckToFalse() method instead of before the return statement.
Indeed it it is contradictory. What you want to achieve is problematic. You want threads waiting on the condition should get result and continue, but a thread that invokes getObject just after notification would not. At least, it is unfair. Whether that thread manages to call getObject before notification or not, is pure random thing. You should decrease indeterminism, not to increase it.
I just want to get know about if this thread is interrupting or not if I'm doing it right?
please give me hint if I'm wrong
public void run(){
int i;
while(!Thread.currentThread().isInterrupted()){
for(i=1;i<=100;i++){
System.out.println("THREAD VALUE AFTER 1 SECOND IS: "+i);
if(i==3){
Thread.currentThread().interrupt();
gotoInform();
break;
}
try{
Thread.currentThread().sleep(1000);////to sleep the Thread for 1 Second (1000ms)
}
catch(Exception e){
System.out.printf("Error"+e);
}
}
}
This is wrong, because if sleep finds that the thread is interrupted, it will throw an InterruptedException and clear the interrupted flag. You then swallow that exception, suppressing any record that the thread was ever interrupted. Instead, you should write something more like this:
public void run(){
for(int i=1;i<=100;i++){
System.out.println("THREAD VALUE AFTER 1 SECOND IS: "+i);
if(i==3){
Thread.currentThread().interrupt();
gotoInform();
break;
}
try{
Thread.currentThread().sleep(1000);
}
catch(final Exception e){
e.printStackTrace();
if(e instanceof InterruptedException) {
// just in case this Runnable is actually called directly,
// rather than in a new thread, don't want to swallow the
// flag:
Thread.currentThread().interrupt();
}
return;
}
}
}
(Note: I'm assuming that this is not "real" code, but rather, that you're just trying to learn how thread interruption works. In "real" code, you should almost never need to interrupt the current thread in this way.)
As mentioned before, a thread interrupting itself is pointless (unless used to re-interrupt itself after catching an InterruptedException) . You're basically using the thread's internal interrupted flag as a conditional variable here - which while it may work is not at all what it's supposed to be used for and will be confusing to anyone else who would need to read your code. Use a loop counter instead as suggested above to make the code much cleaner.
Also, your statement:
System.out.println("THREAD VALUE AFTER 1 SECOND IS: "+i);
is erroneous as it will execute immediately the first time through the loop (when the time is closer to zero seconds).
I just want to get know about if this thread is interrupting or not if I'm doing it right?
#ruakh is correct that it is always a good idea to re-interrupt a thread once InterruptedException is thrown.
However, if the goal of your code is to self-interrupt and no other threads will interrupt the running thread, then you will never get to the sleep() call since break; is called after the thread is interrupted.
If the thread is always just self interrupted then I would just use a flag. Something like:
boolean done = false;
while (!done) {
...
if(i==3){
done = true;
...
}
}
Even though you interrupt your thread, you then call gotoInform() which may call wait()or sleep() itself and cause an InterruptedException. You'll need to make sure that code behaves well and re-interrupts the thread if so.
public class Ex4 extends Thread {
boolean ans;
boolean change=false;
public boolean isPrime(long n, double maxTime) throws RuntimeException {
final Thread a;
Thread b;
final RuntimeException e;
final long num = n ;
final double mtime = maxTime;
a = new Thread(){
public void run(){
try{
ans = Ex4_tester.isPrime(num);
change=true;
}
catch ( RuntimeException exp){
throw exp;
};
}
};
a.start();
try {
sleep((long)mtime);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
if(a.isAlive()){
a.interrupt();
}
if(a.isInterrupted()){
throw new RuntimeException("time for check exceeded");
}
return ans;
}
}
all works fine, except sometimes Ex4_tester.isPrime goes into infinite loop (its ok, it should do that).
the problem that even though the thread gets interrupted the process keeps running and the thread doesnt actually stop
A thread getting interrupted doesn't stop it. It just causes the thread to get out of certain wait and sleep states. To have the thread exit an infinite loop based on input from another thread, put an explicit check against an Atomic<> in the loop and have the control thread modify the state of the atomic variable to where thread 'a' will exit the loop.
Only certain methods like Object.wait() will throw InterruptedException. If your thread doesn't call any of those methods, it won't get interrupted.
In other words, you can't asynchronously interrupt a Java thread. Very few threading systems support asynchronous interruption.
The most easy way is to set your thread to be daemon, that is call a.setDaemon(true) before start. That will make your process will be ended if this is only thread that stayed started.
If you want to interrupt your thread read this documentation for interrupt method
interrupt method causes InterruptedException only when the thread is in certain points of execution (such as sleep). Your code has invalid cancellation policy. You should consider another way of stopping your thread.
An interrupt requires an explicit check at a point where it is safe by design to interrupt a thread. If you don't perform this check (or call a method which does) the thread will keep running.
I have a thread that calls the wait method and can only be awoken when the notify method called from some other class:
class ThreadA {
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
synchronized(b) {
try {
System.out.println("Waiting for b to complete...");
b.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
public void run() {
synchronized(this) {
for(int i=0;i<100;i++) {
total += i;
}
notify();
}
}
}
In the above code if the synchronized block in main, if the ThreadA does not execute first and instead the other synchronization block executing and completes to completion, then ThreadA executes its synchronized block and calls wait, what is going to happen and how it will be notified again?
If ThreadB gets through its synchronized block before ThreadA does, then ThreadA will block indefinitely on the call to wait. It won't somehow be notified that the other thread has already completed.
The problem is that you're trying to use wait and notify in ways that they are not designed to be used. Usually, wait and notify are used to have one thread wait until some condition is true, and then to have another thread signal that the condition may have become true. For example, they're often used as follows:
/* Producer */
synchronized (obj) {
/* Make resource available. */
obj.notify();
}
/* Consumer */
synchronized (obj) {
while (/* resource not available */)
obj.wait();
/* Consume the resource. */
}
The reason that the above code works is that it doesn't matter which thread runs first. If the producer thread creates a resource and no one is waiting on obj, then when the consumer runs it will enter the while loop, notice that the resource has been produced, and then skip the call to wait. It can then consume the resource. If, on the other hand, the consumer runs first, it will notice in the while loop that the resource is not yet available and will wait for some other object to notify it. The other thread can then run, produce the resource, and notify the consumer thread that the resource is available. Once the original thread is awoken, it will notice that the condition of the loop is no longer true and will consume the resource.
More generally, Java suggests that you always call wait in a loop because of spurious notifications in which a thread can wake up from a call to wait without ever being notified of anything. Using the above pattern can prevent this.
In your particular instance, if you want to ensure that ThreadB has finished running before ThreadA executes, you may want to use Thread.join(), which explicitly blocks the calling thread until some other thread executes. More generally, you may want to look into some of the other synchronization primitives provided by Java, as they often are much easier to use than wait and notify.
You could loop and wait until the total has been computed :
synchronized(b) {
while (total == 0) {
b.wait();
}
}
You could also use a higher-level abstraction like a CountDownLatch.
It is possible for ThreadB's run method to complete before you enter the synchronized block in ThreadA.main. In that situation, since the notify call has happened before you started waiting, ThreadA will block forever on the wait call.
A simple workaround would be to grab the lock on b in main before you start the second thread to ensure the wait happens first.
ThreadB b = new ThreadB();
synchronized(b) {
b.start();
...
b.wait();
}
You probably want to use a java.util.concurrent.Semaphore for this.
1) You need to add some flag that is used to communicate between the threads, so that B can signal to A when it is finished. A simple boolean variable is fine, as long as it is only read and written within the synchronized blocks.
synchronized(this) {
for(int i=0;i<100;i++) {
total += i;
}
isDone = true;
notify();
}
2) A needs to loop while waiting. So if your boolean variable was called isDone, and was set to true by threadB, then threadA should have some code like this:
synchronized(b) {
System.out.println("Waiting for b to complete...");
while( ! isDone ) b.wait();
}
In this particular case, there's actually no reason to have the synchronized block in A - since threadB doesn't do anything after it finishes running, and A doesn't do anything except wait for B, threadA could simply call b.join() to block until it finishes. I assume that your actual use case is more complex than this.
Why to make that complex ? Just use join() function of Thread.
ThreadB b = new ThreadB();
b.start();
b.join();
// now print b.total
do not synchronized(thread), don't do it, do not synchronized(thread).. repat: no synchronized(thread) :)
And if you need to wait for the thread 'b' to finish, use b.join(), now your code is free to hang in b.wait()
--
Hopefully the source below can grant you an insight while sync(thread)/notify() I consider bad practice. (cut-cut)
Enjoy
To proceeed below you make sure you have accepted Oracle's License aggreement, found there:
https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewLicense-Start?LicenseUUID=7HeJ_hCwhb4AAAEtmC8ADqmR&ProductUUID=pGqJ_hCwj_AAAAEtB8oADqmS&cnum=&evsref=&sln=
Java sources (incl), called in init(), effectively called by any java c-tor, since java 1.5
private static **synchronized int** nextThreadNum() {
return threadInitNumber++;
}
//join (the method w/ nanos only increase millis by one, if nanos>500000, millis==0 and nanos>0
public final **synchronized** void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
public **synchronized** void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
start0();
if (stopBeforeStart) {
stop0(throwableFromStop);
}
}
//stop1 is called after stop ensures proper priviledges
private final **synchronized** void stop1(Throwable th) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
checkAccess();
if ((this != Thread.currentThread()) ||
(!(th instanceof ThreadDeath))) {
security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
}
}
// A zero status value corresponds to "NEW"
if (threadStatus != 0) {
resume(); // Wake up thread if it was suspended; no-op otherwise
stop0(th);
} else {
// Must do the null arg check that the VM would do with stop0
if (th == null) {
throw new NullPointerException();
}
// Remember this stop attempt for if/when start is used
stopBeforeStart = true;
throwableFromStop = th;
}
}