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 (マークしたとおり) で、メイン スレッドは thread を呼び出しますinterrupt()t2、リソースのロックを取得するのを待っていたため、例外はスローされません。その後、メインスレッドはEnd Main1000 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 を起動しますが、これは Thread1 が保持するロックを 6 秒間取得できません。
  • [2000] メインがスレッド 2 に割り込みフラグを true に設定しますが、スレッド 2 はロックを待機しており、それについて何もしません。
  • [3000]メインエンド
  • [6000] スレッド 1 がスリープを終了し、ロックを解放します
  • [6000] スレッド 2 はそれを取得でき、スリープを開始します (割り込みフラグはオンのままです)。
  • [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 に答える