views:

126

answers:

2

This is a modification of code from the Java tutorial on Concurrency

package threads;

public class SimpleThreads {
 static void threadMessage(String msg) {
  String threadName = Thread.currentThread().getName();
  System.out.format("%s: %s%n", threadName,msg);
 }
 private static class MessageLoop implements Runnable{

  @Override
  public void run() {
   // TODO Auto-generated method stub
   String[] importantInfo= {"apple","bat","chlorine","dog","egg","fog","gun"};
   try {
    for(int i=0;i<importantInfo.length;i++) {
     Thread.sleep(4000);
     threadMessage(importantInfo[i]);
    }
   }catch(InterruptedException ie) {
    threadMessage("i wasn't done");
   }
     }
 }
 /**
  * @param args
  */
 public static void main(String[] args) throws InterruptedException{
  // TODO Auto-generated method stub
  long patience = 100;
  if(args.length > 0)
   try {
    patience = Long.parseLong(args[0]) * 1000;
   }catch(NumberFormatException nfe) {
    System.err.println("argument must be a integer");
    System.exit(1);
   }
  threadMessage("starting message loop thread");
  long startTime = System.currentTimeMillis();
  Thread t = new Thread(new MessageLoop());
  t.start();

  threadMessage("waiting for messageloop thread to finish");
  while(t.isAlive()) {
   threadMessage("still waiting...");
   //t.join(1000);
   if(((System.currentTimeMillis() - startTime) > patience) && t.isAlive()) {
    threadMessage("tired of waiting");
    t.interrupt();
    //t.join();
   }
  }
  threadMessage("finally");
 }

}

and this is the output

main: starting message loop thread
main: waiting for messageloop thread to finish
main: still waiting...
main: still waiting...
...(repeats about 100 times)
main: still waiting...
main: still waiting...
main: still waiting...
main: still waiting...
main: tired of waiting
main: still waiting...
main: tired of waiting
main: still waiting...
main: tired of waiting
main: still waiting...
main: tired of waiting
main: still waiting...
main: tired of waiting
Thread-0: i wasn't done
main: finally

I expected that after the first(and supposedly only) main: tired of waiting I would see Thread-0: i wasn't done but main: tired of waiting appears 5 times -- why is that?

+3  A: 

Thread.Interrupt() just sends an interrupt (signal / exception) to the target thread; it doesn't kill it immediately.

Also, there can be a delay between when you send the interrupt and when it is received and processed by the target thread; context switches are not guaranteed to be immediate.

You can encourage (but not force) the JVM to context switch more quickly by either doing some form of blocking operation (such as I/O or a sleep), or by calling Thread.yield().

RickNZ
`main: tired of waiting` could happen N times -- 5 was just an arbitrary number based on VM timing.
non sequitor
sure, because the time for the context switches to happen is also (semi) arbitrary.
RickNZ
A: 

Thread.interrupt() does not kill or interrupt the Thread.
It just interrupts some methods like sleep, wait, join, blocked I/O on interruptible channels or a blocked Selector. Otherwise it just sets the interrupted flag of the Thread and it is up to you to test this flag.
If you remove the sleep in the above code, the interrupt will have no visible effect.

The Thread will (may) be interrupted a couple of times because the actual Thread (main loop) continues running till the system changes to the interrupted Thread. After interrupting you can add an sleep() or yield() (join(), as indicated, should also work) to allow the interrupted Thread to run

    threadMessage("tired of waiting");
    t.interrupt();
    t.yield();

See also documentation of interrupt

Carlos Heuberger