15

私はスレッドのいくつかのパズルを探していますが、なぜ以下が一貫して印刷されるのか理解できません999999

class Job extends Thread {  
    private Integer number = 0;  
    public void run() {  
        for (int i = 1; i < 1000000; i++) {  
            number++;  
        }  
    }  
    public Integer getNumber() {  
        return number;  
    }  
}  
public class Test {  
    public static void main(String[] args)   
    throws InterruptedException {  
        Job thread = new Job();  
        thread.start(); 
        synchronized (thread) {  
            thread.wait();  
        }  
        System.out.println(thread.getNumber());  
    }  
}   

同じロックにはありませんnotify(そして、偽のウェイクアップは無視されているようです)。
スレッドが終了した場合、通知は通知されますか?
どうしてmain結果を印刷し、「行き詰まって」待たされないのですか?

4

6 に答える 6

13

Java 7 Thread.join(long)の Javadoc で

この実装は、this.isAlive を条件とする this.wait 呼び出しのループを使用します。スレッドが終了すると、 this.notifyAll メソッドが呼び出されます。アプリケーションが Thread インスタンスで wait、notify、または notifyAll を使用しないことをお勧めします。

この方法でスレッドを直接使用することは、実用的ではないと考えられています。注: wait() は、さまざまな理由で終了する可能性があります。


@Voo のコメントに関連するパズルに基づいています。要点は、混乱を招く可能性が高いため、Thread の内部動作で遊んではいけないということです。

public static String getName() {
    return "MyProgram";
}
public static void main(String... args) {
    new Thread() {
       public void run() {
           System.out.println("My program is " + getName());
        }
    }.start();
}

このプログラムは何を印刷しますか?

于 2012-07-23T09:33:34.483 に答える
3

明確にするために、私はあなたのコードをこれに変更しました:

Job thread = new Job();
thread.start();
final Object lock = new Object();
synchronized (lock) { lock.wait(); }
System.out.println(thread.getNumber());

今それはブロックします。これは、@Nitramが彼の回答で説明したことの直接の確認です。実装コードを確認したい場合Threadは、これが観察された動作である理由が非常に明白になります。

于 2012-07-23T09:14:35.003 に答える
3

注:この回答は大幅に編集されています。


この動作の理由は、「誰か」がnotifyAll内部的に呼び出しているためです。この「誰か」は、ここの C ソースで「見る」ことができるように、JVM そのものです。

http://hg.openjdk.java.net/jdk7/hotspot/hotspot/file/f95d63e2154a/src/share/vm/runtime/thread.cpp

1531 行目で、メソッドensure_joinは を呼び出しますnotifyAll。これは、(Marko などによって指摘されているように) のwait呼び出しに対応するものです。java.lang.Thread#join

ensure_join次に、メソッドの 1664 行目で呼び出されJavaThread::exitます。


これは「内部簿記」であるため、誰もこの動作に頼るべきではありません。

于 2012-07-23T09:28:57.403 に答える
2

Threadスレッドの実行が終了すると、待機中のすべてのスレッドに通知するだけです。これを行う理由は提案されていませんが、機能します。スレッドの最後で同期するには、Thread.join.

于 2012-07-23T09:20:50.133 に答える
0

スレッドが終了するとスレッド オブジェクトに自動的に通知されるため、メイン スレッドが停止することはありません。

于 2012-07-23T09:17:18.907 に答える
-1

まあ....通知は、ロックされたオブジェクトを待っているスレッドに時期尚早に通知する目的を果たします。Notify を使用しない場合、確実に終了するとロックが解除されます。

So that is equivalent to notify

いいえ、そうではありません..以下の状況を考えてみましょう。

class Job extends Thread {  
    private Integer number = 0;  
    public void run() {

       synchronized(this) {
       for (int i = 1; i < 1000000; i++) {  
            number++;  
        }  
        notify();     //releases lock here and your main thread continues
        do sumthing...
        do sumthing...
        }  
    }
    public Integer getNumber() {  
        return number;  
    }  
}  

notify() を使用しない場合 ...ロックは、すべての合計を行った後にのみ解放されます..

于 2012-07-23T09:16:43.133 に答える