Dienstag, 13. Dezember 2011

When the timeout fails in Thread.join

There is a little danger using the join with a timeout. The implementation will call a wait on the thread instance. For this purpose the calling thread A has to get the monitor on the thread B he wants to join. During the wait this monitor is suspended, but after the wait the thread has to enter the monitor again. If now the thread B obtains the monitor itself and holds it for a long time (forever), the timeout of the wait method (inside the join) may be finished, but the monitor can not be regained after the wait. Therefore the thread A will stuck in the join method for a long time (forever) even with the timeout...

public class Test {

  private static final String DATE_PATTERN = "HH:mm:ss.SSS";
  public static FastDateFormat DATE_FORMAT = FastDateFormat.getInstance(DATE_PATTERN);

  public static String time() {
    return DATE_FORMAT.format(new Date());
  }

  public static void doSleep(long ms) {
    try {
      Thread.sleep(ms);
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
    }
  }

  public static void main(String[] args) throws InterruptedException {
    Thread t = new Thread() {
      @Override
      public void run() {
        System.out.println(time() + " T: sleep(2000)");
        doSleep(2000);
        System.out.println(time() + " T: sleep(2000) finished");
        System.out.println(time() + " T: sync");
        synchronized (this) {
          System.out.println(time() + " T: sleep(60000)");
          doSleep(60000);
          System.out.println(time() + " T: sleep(60000) finished");
        }
        System.out.println(time() + " T: finished");
      }
    };
    System.out.println(time() + " M: t.start()");
    t.start();
    System.out.println(time() + " M: t.join(5000)");
    t.join(5000);
    System.out.println(time() + " M: finished");
  }
}

Keine Kommentare:

Kommentar veröffentlichen