1
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()thread t2,但由于它正在等待获取资源的锁,它不会引发任何异常。之后,主线程End Main在等待 1000 ns 后打印“”。换句话说,主线程已经完成了它的任务,那么什么会t2.interrupt()因为它抛出异常而再次触发呢?

4

3 回答 3

3

以下是您的程序的运行方式,带有时间戳:

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

为什么(括号中的时间戳)?

  • [0000] main启动Thread1,获取锁并休眠6秒
  • [1000] main启动Thread2,6秒内无法获取Thread1持有的锁
  • [2000] 主中断 Thread2 将其中断标志设置为 true,但 Thread2 正在等待锁定并且不对其执行任何操作
  • [3000] 主端
  • [6000] Thread1 完成休眠并释放锁
  • [6000] Thread2 可以获取它并开始休眠(它的中断标志仍然打开)
  • 【6000】sleep检测到Thread2被中断,立即抛出异常
  • [6000] Thread2 结束,允许 JVM 退出
于 2013-08-06T13:52:32.470 回答
1

你需要一个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
于 2013-08-06T13:57:29.497 回答
0

这是因为当主线程关闭时,JVM 会杀死你的线程。

于 2013-08-06T14:00:08.547 回答