Использование метода прерывания

public class TwoThreads {
        private static Object resource = new Object();

        private static void delay(long n) {
            try 
            { 
                Thread.sleep(n);
            }
            catch (Exception e)
            { 

                e.printStackTrace();
            }
        }

        public static void main(String[] args) {
            System.out.print("StartMain ");
            new Thread1().start();
            delay(1000);                       //dealay 1
            Thread t2 = new Thread2();
            t2.start();   
            delay(1000);                      // delay 2    
            t2.interrupt();                   //step 7
            delay(1000);                      //delay 3
            System.out.print("EndMain ");
        }

        static class Thread1 extends Thread {
            public void run() {
                synchronized (resource) {
                    System.out.print("Startl ");
                    delay(6000);
                    System.out.print("End1 ");
                }
            }
        }

        static class Thread2 extends Thread {
            public void run() {
                synchronized (resource) {
                    System.out.print("Start2 ");
                    delay(2000);
                    System.out.print("End2 ");
                }
            }
        }
    }

На шаге 7 (как я уже отметил) основной поток вызывает interrupt() в потоке t2, но поскольку он ожидал получения блокировки ресурса, он не выдает никаких исключений. После этого основной поток выводит «End Main» после ожидания 1000 нс. Другими словами, основной поток завершил свою задачу, так что же снова вызывает t2.interrupt(), потому что после этого он выдает исключение?


person Sunny    schedule 06.08.2013    source источник


Ответы (3)


Вот как работает ваша программа с отметками времени:

0000 StartMain 
0000 Startl 
3000 EndMain 
6000 End1 
6000 Start2 
6000 End2 

Почему (временные метки в скобках)?

  • [0000] main запускает Thread1, который блокируется и приостанавливается на 6 секунд.
  • [1000] main запускает Thread2, который не может получить блокировку, удерживаемую Thread1 в течение 6 секунд.
  • [2000] main прерывает Thread2, устанавливая флаг прерывания в true, но Thread2 ожидает блокировку и ничего с этим не делает
  • [3000] основные концы
  • [6000] Thread1 завершает спящий режим и снимает блокировку.
  • [6000] Thread2 может получить его и начинает спать (его флаг прерывания все еще включен)
  • [6000] sleep обнаруживает, что Thread2 был прерван, и немедленно генерирует исключение
  • [6000] Thread2 завершается, позволяя JVM выйти
person assylias    schedule 06.08.2013

Вам нужен ReentrantLock.

public class TwoThreads {
  private static Lock lock = new ReentrantLock();

  private static void delay(long n) {
    try {
      Thread.sleep(n);
    } catch (Exception e) {

      e.printStackTrace();
    }
  }

  public static void main(String[] args) {
    System.out.print("StartMain ");
    new Thread1().start();
    delay(1000);                       //dealay 1
    Thread t2 = new Thread2();
    t2.start();
    delay(1000);                      // delay 2    
    t2.interrupt();                   //step 7
    delay(1000);                      //delay 3
    System.out.print("EndMain ");
  }

  static class Thread1 extends Thread {
    public void run() {
      try {
        lock.lockInterruptibly();
        try {
          System.out.print("Startl ");
          delay(6000);
          System.out.print("End1 ");
        } finally {
          lock.unlock();
        }
      } catch (InterruptedException ex) {
        // Interrupted.
      }
    }

  }

  static class Thread2 extends Thread {
    public void run() {
      try {
        lock.lockInterruptibly();
        try {
          System.out.print("Start2 ");
          delay(2000);
          System.out.print("End2 ");
        } finally {
          lock.unlock();
        }
      } catch (InterruptedException ex) {
        // Interrupted.
      }
    }

  }
}

Отпечатки:

StartMain Startl EndMain End1
person OldCurmudgeon    schedule 06.08.2013

Это потому, что JVM убивает ваши потоки, когда основной поток закрывается.

person Holger    schedule 06.08.2013
comment
это не потоки демона, они не будут убиты, когда основной поток завершится. - person Nathan Hughes; 06.08.2013