Why does interrupt() interrupt two threads in quick succession? - java

I want to start a thread, interrupt it and start a new thread. The Problem is, that this doesn't really work. The first thread starts and gets interrupted, but the following thread gets interrupted before it even can start. So interrupt() interrupts the old and the new thread. The output looks like this:
run()-method starts
Thread Counter:0
Thread Counter:1
Thread Counter:2
Thread Counter:3
Thread Counter:4
Thread Counter:5
Thread Counter:6
8 seconds are over
Thread is not null
Thread will be interrupted now
catch
run()-method starts
catch
8 seconds are over
Thread is not null
Thread will be interrupted now
....
You can see that the thread starts the first time. Then the thread gets interrupted and 'catch' is called. So far, so good. After this, the next thread is going to start, but this time the thread gets interrupted immediately and 'catch' is called right after 'run()-method starts'.
So, I can't figure out why this is happening. I don't want two threads being interrupted in quick succession.
Here is my code:
public class MyRunnable {
static Thread myThread;
static boolean stop;
static Runnable myRunny = new Runnable() {
#Override
public void run() {
System.out.println("run()-method starts");
try {
int j = 0;
while (!stop) {
Thread.sleep(1000);
System.out.println("Thread Counter:"+j);
j++;
}
} catch (InterruptedException e) {
System.out.println("catch");
myThread.interrupt();
}
};
};
public static void main(String[] args){
myThread = null;
while(true) {
stop = false;
if(myThread != null) {
System.out.println("Thread is not null ");
System.out.println("Thread will be interrupted now");
myThread.interrupt();
}
myThread = new Thread(myRunny);
myThread.start();
try {
Thread.sleep(8000);
System.out.print("8 seconds are over "+ "\n");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

catch (InterruptedException e) {
System.out.println("catch");
myThread.interrupt();
}
myThread field is replaced with new reference before calling myThread.interrupt(), so you interrupt the new thread!

So interrupt() interrupts the old and the new thread.
Your diagnosis is incorrect. A call to Thread.interrupt will interrupt one thread once.
What your example is doing is interrupting one thread, and that thread is catching InterruptedException and interrupting a second thread in the exception handler. Two calls to interrupt are being made in quick succession on different threads.
I don't want two threads being interrupted in quick succession.
Well change
} catch (InterruptedException e) {
System.out.println("catch");
myThread.interrupt();
}
to
} catch (InterruptedException e) {
System.out.println("catch");
}

Related

Why thread object wait method don't need notify method to wake up?

When I call wait() method on a thread object, the waiting thread will be waken up when the synchrized thread finishes run, why is the thread object behaviors different from plain object where wait()?
Thread thread1 = new Thread(()-> {
System.out.println("thread 1 start");
try {
Thread.sleep(3000);
System.out.println("thread over");
} catch (InterruptedException e) {
e.printStackTrace();
}});
thread1.start();
synchronized (thread1) {
try {
thread1.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("main thread wake up");
I expected main thread does not wake up after 3s, but not.
The javadoc says:
As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.

For below program, when threads finish their work, why doesn't main thread stops?

This program works fine by printing alternate numbers via different threads but when all the numbers from 0-9 are printed Why does this program not stop? I have to manually stop my application.
public class EvenOddPrinter implements Runnable{
private AtomicInteger num = new AtomicInteger(0);
private Object lock = new Object();
#Override
public void run() {
synchronized (lock){
while (num.get()<10){
System.out.println(num.getAndAdd(1) + " - "+Thread.currentThread().getName());
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Executor {
public static void main(String[] args) throws InterruptedException {
EvenOddPrinter eop = new EvenOddPrinter();
Thread t1 = new Thread(eop);
Thread t2 = new Thread(eop);
t1.start();
t2.start();
}
}
that's because in the last Thread getting stuck at wait. notifyAll will notify all waiting thread if any there and release lock.
while (num.get()<10){
// existing implementation
}
lock.notifyAll();
The second thread t2 keeps waiting on the lock in the end, and t1 doesnt do the notify() anymore because the while condition becomes false. You must put a lock.notify(); statement outside of the while loop.
As soon as the number reached 8 the first thread calls notify() and goes to wait(). Second thread then makes the number 9 and calls notify() and goes to wait(). First thread is then not able to go inside the loop as specified in the condition, therefore, it exits the synchronized and block and finishes but second thread is still waiting. There has to be a mechanism to notifyAll() as soon as one of the threads exits the synchronized block which is exactly what I did.
#Override
public void run() {
synchronized (lock){
while (num.get()<10){
System.out.println(num.getAndAdd(1) + " - "+Thread.currentThread().getName());
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notifyAll();
}
Also, lock is pointless when I am using AtomicInteger (or the other way round).

How to use java Thread.currentThread().interrupt()

if I override my run function as ,
Thread t = new Thread(){
public void run(){
try {
if(Thread.currentThread().isInterrupted()) {
doSomePrcocess() // is the isInerrupted() flag seeting to true?
return; //Terminates the current Thread
}
//otherwise
runScript();
} catch (Exception e) {
e.printStackTrace();
}
}
};
t.start();
and then If I call, Thread.currentThread().interrupt() from any point in the code, should the thread halt there and start running doSomeProcess() at that point? if yes, then how the interrupted flag gets to set true? If no, how to do this?
If thread is in sleeping or waiting state calling the interrupt() method on the thread, breaks out the sleeping or waiting state
throwing InterruptedException
If the thread is not in the sleeping or waiting state, calling the
interrupt() method performs normal behaviour and doesn't interrupt the thread but sets the interrupt flag to true.
Thread class has provision to deal with thread interruption as
public void interrupt()
public static boolean interrupted()
public boolean isInterrupted()
If you intend to go with the only once execution of doSomePrcocess then you have to go with which will check and clear the Thread interruption state for successive calls.
public static boolean interrupted()
Using below will only check the status and no modification.
public boolean isInterrupted()
I have got a running example with comments in your code below. Try running it a few times to see if it clarifies your concept.
Normally you would interrupt a thread from another thread and yes doSomeProcess will get invoked in the next cycle of the loop which could be 1 ms after the thread was interrupted or 1 hour after depending on the logic implemented in your methods.
public class InterruptTest {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
public void run() {
while (true) {
try {
if (Thread.currentThread().isInterrupted()) {
doSomePrcocess(); // is the isInerrupted() flag seeting to true? - Yes
return; // Terminates the current Thread - yes
}
// otherwise
runScript();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void runScript() {
System.out.println("runScript interrupted status:" + this.isInterrupted());
sleepy(100);
}
private void doSomePrcocess() {
System.out.println("doSomePrcocess interrupted status:" + this.isInterrupted());
sleepy(500);
}
private void sleepy(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Thread.currentThread().interrupt(); // try commenting this out to see what happens.
}
}
};
t.start();
Thread.sleep(1000);
t.interrupt(); // generally you would call interrupt on another thread.
}
}
No, it doesn't work like that. The isInterrupted method checks if the flag is set, it does not declare a handler. There is no way to define a central handler that will automatically be called when a thread is interrupted. What you can do is to catch InterruptedException and call the handler, plus check the interrupt flag regularly to see if it is time to stop.

Synchronize in Java not behaving correctly?

for (int i = 0; i < 3; i++) {
list.add("test" + i);
}
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
synchronized (list) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
list.add("test3");
}
}
});
thread.start();
synchronized (list) {
System.out.println(list);
}
What I'm not understanding right now is, the printout doesn't contain "test3". Shouldn't synchronizing list during the thread halt the println at the end?
So they should be in order of:
Thread.sleep();
list.add("test3");
println(list);
What's going on?
Shouldn't synchronizing list during the thread halt the println at the end?
That would only be true if the second thread's run() method's execution (and in particular the execution of the synchronized (list) statement within it) started before the synchronized (list) statement of the main thread is executed.
Calling thread.start(); before synchronized (list) {System.out.println(list);} does not guarantee the second thread will start running before synchronized (list) {System.out.println(list);} is executed.
What I'm not understanding right now is, the printout doesn't contain
"test3". Shouldn't synchronizing list during the thread halt the
println at the end?
That would imply that the Thread you started would get the lock before the main thread. There is no way to guarantee that in Java. In fact, it seemed to work the other way round, main thread takes lock before the second thread, blocking the second thread from taking the lock.
You could try to use the wait/notify mechanism to ensure the main thread is waiting for the other thread to terminate:
import java.util.ArrayList;
for (int i = 0; i < 3; i++) {
list.add("test" + i);
}
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
synchronized (list) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
list.add("test3");
// Notify the main thread
list.notify();
}
}
});
thread.start();
synchronized (list) {
try {
// wait for the other thread for a specified time to terminate
// this will temporary release the lock for the second thread.
list.wait(5000);
} catch (InterruptedException e) {
// see above..
e.printStackTrace();
}
System.out.println(list);
}

How can I start a thread from another and restart a thread after execution?

I have 2 threads, the "main" thread which starts a secondary thread to run a little process.
The "main" thread must wait for the secondary thread for a few of seconds to complete the process, after that time, the "main" thread must start again no matter what happened with the process of the secondary thread.
If the secondary process ended earlier, the "main" thread must start to work again.
How can I start a thread from another, wait for the end of execution, and restart the thread after?
I have a code here, but the ExampleRun class, must wait, for example, 10 sec and start again, no matter what happend with MyProcess
public class ExampleRun {
public static void main(String[] args) {
MyProcess t = new MyProcess();
t.start();
synchronized (t) {
try {
t.wait();
} catch (InterruptedException e) {
System.out.println("Error");
}
}
}
}
public class MyProcess extends Thread {
public void run() {
System.out.println("start");
synchronized (this) {
for (int i = 0; i < 5; i++) {
try {
System.out.println("I sleep");
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
flag = true;
System.out.println("Wake up");
notify();
}
}
}
The simplest way to achieve what you want is to use Thread.join(timeout).
Also, do not use synchronized, wait, or notify on Thread objects. This will interfere with the Thread.join implementation. See the documentation for details.
Here's what your main program would look like:
public static void main(String[] args) {
MyProcess t = new MyProcess();
t.start();
try {
t.join(10000L);
} catch (InterruptedException ie) {
System.out.println("interrupted");
}
System.out.println("Main thread resumes");
}
Note that when the main thread resumes after the join() call, it can't tell whether the child thread completed or whether the call timed out. To test this, call t.isAlive().
Your child thread of course could do anything, but it's important for it not to use synchronized, wait, or notify on itself. For example, here's a rewrite that avoids using these calls:
class MyProcess extends Thread {
public void run() {
System.out.println("MyProcess starts");
for (int i = 0; i < 5; i++) {
try {
System.out.println("MyProcess sleeps");
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("MyProcess finishes");
}
}
You can do this with a simple lock method:
public static void main (String[] args)
{
// create new lock object
Object lock = new Object();
// create and start thread
Thread t = new Thread(() ->
{
// try to sleep 1 sec
try { Thread.sleep(1000); }
catch (InterruptedException e) { /* do something */ }
// notify main thread
synchronized (lock) { lock.notifyAll(); }
};
t.start();
// wait for second thread to finish
synchronized (lock)
{
while (t.isAlive())
lock.wait();
}
// second thread finished
System.out.println("second thread finished :)");
}
You could call Thread.join() on the Thread you want to wait for, per the Javadoc,
Waits for this thread to die.
Alternatively, you could use a Future and simply call get(), from its' Javadoc,
Waits if necessary for the computation to complete, and then retrieves its result.

Categories