views:

105

answers:

4

I know that this is ill advised but still i am trying to look into a method of interrupting a thread which hangs, from another thread which is keeping time.

What i do is: I start the monitor thread just before a questionable network operation is about to happen. This thread is supposed to monitor the time elapsed since it was started and if the time exceeds some threshold value, it kills the thread that initially started it. In order to inform this new thread , which thread is to be killed , the object of the new thread , is passed an object of the Thread to be monitored.

In a nutshell, this is what happens :

A creates B , B creates C , B tells C about itself , C keeps time , if time expires C kills B (I pass the details to C after in B's run method using "currentThread()" and I have confirmed that the correct object is indeed being passed)

Now, the problem is that , this , is not working , for some reason , the call to B.interrupt() is killing C itself.

[Note : Uppercase letters denote thread names]

A: 

This is actually normal behaviour if you ask me. If you interrupt B, it will be garbage collected. Since the only reference to C is then also GC'd, it will cease to exist/run.

The best idea may be to make sure that there is a thread that manages thread B and C (and injects thread C into thread B). That way, there is always a reference to thread C and it can kill of thread B. (but you have to be careful what you do with thread B in the management thread)

Kurt Du Bois
Actually , that is what i believed , however , what i am observing is that C gets destroyed and B continues to exist.
Nikhil Raktale
I think threads have references from ThreadGroup objects. I do not thread C is CG'd in this example
Georgy Bolyuba
Yeah, threads are not GCd like that.
Enno Shioji
-1 Threads are not GC'd like that.
Tim Bender
+1  A: 

Check if you are getting SecurityException when calling B.interrupt(). Also, are you sure that your B.interrupt() does not simply returns and thread C finishes successfully? Based on javadocs, it looks like thread C's call of B.interrupt() will set thread B's interrupt status and finish running. I do not think thread B will get any exception in your case, unless it meets special requirements (like, waiting on monitor, waiting on InterruptibleChannel, etc).

Georgy Bolyuba
As far as i can see , no exception of any sort is being thrown anywhere in the code
Nikhil Raktale
Can you please post the code of your monitoring thread?
Georgy Bolyuba
+1  A: 

I think something is wrong with your code (unless I didn't get your spec right). The below code runs as expected (sorry for the horrible nested structure):

Output was:

C is about to interrupt B
B is interrupted
C is still alive... is B alive yet?false

Code was:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;


public class Scrap {
    public static void main(String[] args) {
        Thread A = new Thread() {
            @Override
            public void run() {
                Thread B = new Thread() {
                    @Override
                    public void run() {
                        final CountDownLatch latch = new CountDownLatch(1);
                        final AtomicReference<Thread> pointer = new AtomicReference<Thread>();
                        Thread C = new Thread() {
                            @Override
                            public void run() {
                                try {
                                    //wait for B to be ready
                                    latch.await();
                                    Thread.sleep(2000);
                                    System.out.println("C is about to interrupt B");
                                    pointer.get().interrupt();
                                    Thread.sleep(2000);
                                    System.out.println("C is still alive... is B alive yet? " + pointer.get().isAlive());

                                } catch (InterruptedException e) {
                                    System.out.println("C interrupted");
                                    return;
                                }
                            }
                        };//C
                        C.start();
                        latch.countDown();
                        //Not sure how you did it, so just going with this:
                        pointer.set(Thread.currentThread());


                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            System.out.println("B is interrupted");
                            return;
                        }
                        System.out.println("B survived");

                    }
                };//B
                B.start();
            }
        };
        A.start();
    }
}

My (wild) guess would be inter-thread visibility. In the above code, I'm using atomic reference to ensure visibility. In case you did not do that, it is possible that whatever field you passed Thread B's reference ('s value) might have been invisible to C. Then when C tries to interrupt this Thread object, it sees null and the interrupt results in NullPointerExceptin, and somehow you are not noticing it?

Enno Shioji
+1  A: 

Another possibility is that, C interrupts successfully and returns, but B does not respond to that. This is quite possible because interruption has only effect if B is coded accordingly.

There are 2 way to react to interruption.
1. Check interruption flag (typically before operations that take long)

if(Thread.currentThread().isInterrupted()){
    log.info("Cancel requested");
    return;
}
someStuffThatTakesLongTimeToExecute();

2.Act on interruption exception

catch(InterruptedException e){
    log.info("Cancel Requested");

    //Preserve interrupted status.
    //If this class is the owner of the thread,
    //Not necessary.
    Thread.currentThread.interrupt(); 

    return;
}
Enno Shioji