These are the 3 classes I have:
public class ChildThread extends Thread {
#Override
public void run() {
while (true) {
System.out.println("Child thread is running.");
if (Thread.currentThread().isInterrupted()) {
System.out.println("Child thread is interrupted.");
return;
}
}
}
}
public class MainThread extends Thread{
public Thread childThread = new ChildThread();
#Override
public void run() {
childThread.start();
}
}
public class App {
public static void main(String[] args) {
MainThread mainThread = new MainThread();
mainThread.start();
mainThread.childThread.interrupt();
}
}
When I run this, the child thread doesn't seem to be ever interrupted. It keeps printing: "Child thread is running."
However, if I put a debug breakpoint at mainThread.childThread.interrupt();, child thread will get interrupted.
And also, if I change App class like the following:
public class App {
public static void main(String[] args) throws Exception{
ChildThread childThread = new ChildThread();
childThread.start();
Thread.sleep(3000);
childThread.interrupt();
}
}
it works again. Child thread gets interrupted and stopped printing after 3 seconds.
It seems that the behaviors are different interrupting from a thread that directly started a child thread, and from a thread that didn't directly start a child thread. And it's also different depending on whether there's a breakpoint or not. It's so weird to me. How could this work in a complex system? I don't think a complex system can guarantee all interruption signals are from the original starters of threads.
Could anyone help explain this? I can't find anywhere that seem to have an answer.
You need the Thread.sleep before interrupting otherwise, you are interrupting before the child thread even before it has gotten a chance to start running. As per the API specs "Interrupting a thread that is not alive need not have any effect.". So, in affect, the interrupt statement is being ignored as at the time the thread is not active. Without the sleep, the thread become active AFTER the interrupt - hence is never interrupted.
public class App {
public static void main(String[] args) throws InterruptedException {
MainThread mainThread = new MainThread();
mainThread.start();
Thread.sleep(1); // <== This line is needed as otherwise, the next line will
// interrupt the thread, even before it has started running!
mainThread.childThread.interrupt();
}
}
Related
According to the information I've got so far, I've understood that Thread.sleep() pauses the thread where the method is called. For example, if I call it within the main method it pauses the execution of main. if I call it inside the run of a certain thread, it would only pause that thread.
I need an expertise to confirm my understanding as I feel lost among the too much information on web.
I've been practicing to apply this, throw the following:
a Thread class, Player1:
public class Player1 extends Thread{
public void run()
{
try {
System.out.println("I'm going to sleep");
Thread.sleep(2000);
System.out.println("I'm awake");
} catch (InterruptedException ex) {
}
}
}
a Thread class, Client:
public class Clients extends Thread {
public void run()
{
printer2(10);
}
public synchronized static void printer2(int val)
{
System.out.println(val);
System.out.println(val);
System.out.println(val);
System.out.println(val);
System.out.println(val);
System.out.println(val);
}
}
they're called inside main method:
public static void main(String[] args) throws InterruptedException {
Clients c1 = new Clients(10);
Player1 p = new Player1();
p.start();
c1.start();
}
What happens (according to my understanding): the sleep is applied only to the execution of the player1 thread not to the main thread or the client thread.
Similarly, if I add a sleep method in the run of the Clients thread, it would sleep independently of the other Thread. for instance: this sleeps for its own 1 second and this sleeps for its 1 second as well (even if those 2 1 seconds overlap)
Correct me if I'm wrong please
Thanks in advance!
I am running following peice of code to understand daemon threads concept and thread termination. the program keeps printing even after main method is done. Am I missing something here?
package threading;
public class ThreadInterruption {
public static void main(String[] args) {
Thread t = new Thread(new RanThread());
t.start();
t.setDaemon(true);
t.interrupt();
}
}
class RanThread implements Runnable{
#Override
public void run() {
int count=0;
while(true) {
System.out.println("Ha Ha Ha "+ count);
count=count+1;
}
}
}
Thanks in advance.
You must set the thread as a daemon before you start it.
If you read the API docs it states "This method must be invoked before the thread is started."
So swap the start and setDaemon lines and you should be good.
I'd like to check to see if a Thread is Interrupted, from some other Thread, without polling this to check - i.e. some kind of monitor.
Specifically, what I am trying to do is force-kill (Stop) a Thread when it is Interrupted. I will include a code example below of a trivial example of what I have done so far - it works, but polling to check if the Thread is interrupted is sub-optimal and I would like to avoid this.
public class ThreadTest
{
public static void main(final String[] args) throws InterruptedException
{
final Thread outerThread = new Thread()
{
#Override
public void run()
{
// Need to externally monitor the thread to detect and process interrupts (for cancellation)
final Thread thread = Thread.currentThread();
new Thread()
{
#Override
public void run()
{
while (true)
{
try
{
Thread.sleep(500);
}
catch (final InterruptedException e)
{}
if (thread.isInterrupted())
{
// Then kill it
thread.stop();
return;
}
}
}
}.start();
uninterruptibleForever();
}
};
outerThread.start();
// Ensure the thread has time to start up
Thread.sleep(500);
outerThread.interrupt();
// The thread should terminate at this point and not continue.
}
/** Some arbitrary task that runs forever and ignores interrupts */
public static void uninterruptibleForever()
{
while (true)
{
System.out.println(MessageFormat.format("I''m still running at {0}", new Date().toLocaleString()));
}
}
}
I can't recommend strongly enough that you don't use Thread#stop().
It should never have existed, was deprecated very quickly and frankly should have been removed about 20 years ago.
You have no idea what the thread is doing when you stop it and it is very easy to corrupt shared objects and leave external resources (e.g. files) in an invalid state.
Suppose the thread is in the middle of resizing a shared ArrayList<> there's risk the object will be corrupted and your whole program fails intermittently in ways you cannot fix.
Do not use Thread#stop() it is broken and cannot be fixed.
It's a terrible feature of Java that it leads people into invalid techniques regarding threads.
Caveat over - how about just overriding interrupt() in a sub-class?
public void interrupt(){
this.stop();
}
You've decided to sub-class Thread (rather than Runnable) so this will "work". "work" in the sense of what you're doing. Not actually work or anything.
The only valid way to solve this is have the thread you want to terminate co-operate by responding to interrupt() as an instruction to come to a suitable point and then terminate cleanly.
Or you can create another flag indicating the thread should end.
I don't know why you need to monitor the thread externally. But here is a small sample how you could do it if you really need it:
import java.util.LinkedList;
import java.util.List;
public abstract class MonitoredCallable implements Runnable {
private final List<InterruptedHandler> interruptedHandlers = new LinkedList<>();
protected abstract void runInternal() throws Exception;
#Override
public final void run() {
try {
runInternal();
} catch(Exception ex) {
}
for (InterruptedHandler interruptedHandler : interruptedHandlers) {
interruptedHandler.threadInterrupted(this);
}
}
public void addInterruptedHandler(InterruptedHandler interruptedHandler) {
this.interruptedHandlers.add(interruptedHandler);
}
public static interface InterruptedHandler {
void threadInterrupted(Thread t);
}
}
Now just use it like this:
MonitoredThread mt = new MonitoredThread() {
#Override
protected void runInternal() throws Exception {
//dosomething
}
};
mt.addInterruptedHandler(t->t.stop());
I have just seen problem in my below code in isAlive method , it will return false even thread.start() method has been called, even i also tried to add some sleep in main thread as well as my thread object but still it gives same behavior.
public class ThreadBehaviour implements Runnable {
private Thread t;
ThreadBehaviour() {
t = new Thread();
t.setName("hello");
}
public void start() throws InterruptedException {
if (!t.isAlive()) {
t.start();
//Thread.currentThread().sleep(1000L);
//t.sleep(3000l);
System.out.println(t.getName() + " Running....." + t.isAlive());// why is Alive is false here?
}
}
public static void main(String args[]) throws InterruptedException {
ThreadBehaviour myThread = new ThreadBehaviour();
myThread.start();
}
#Override
public void run() {
t.run();
}
}
Your Thread that you made does nothing, so it instantly finishes and dies.
Consider this:
t = new Thread(() -> {
while (true) {
System.out.println("I'm running...");
}
});
and try again.
Read the java doc
isAlive();
Tests if this thread is alive. A thread is alive if it has been
started and has not yet died.
You only instantiate in constructor without started. So the thread is not started.
This is good example of stopping thread.
How to stop a java thread gracefully?
But when I try to check this example I received infinite loop.
This is my code:
public class Num {
public void crash(ManualStopping t1) {
t1.stopMe();
}
public static void main(String[] args) {
Num num = new Num();
ManualStopping t1 = new ManualStopping();
t1.run();
System.out.println("Main thread");
num.crash(t1);
}
}
class ManualStopping extends Thread {
volatile boolean finished = false;
public void stopMe() {
finished = true;
}
public void run() {
while (!finished) {
System.out.println("I'm alive");
}
}
}
I think you need to start your thread - not run it. By calling run, you are just making a normal method call, not running a separate thread.
Nothing in your code calls the stopMe method on ManualStopping. isInterrupted() is a test that doesn't change the state of the thread. And as #DaveHowes points out, you don't even start a separate thread.
t1.run(); Change it to t1.start().
Whats happening is that the thread you intend to spawn is not actually running as a separate thread. Instead the loop
while(!finished){ System.out.println("I'm alive"); }
is running on the main thread and your code num.crash(t1); never actually gets invoked. This is causing the infinite loop.