web-dev-qa-db-ja.com

同期ブロックを同時に実行する2つのスレッド

以下は、Threadが同期ブロックに入り、5秒間待機してから終了するコードです。 2つのThreadインスタンスを同時に開始しました。

スレッドの1つが同期オブジェクトのロックを所有し、もう1つが待機することを期待していました。 5秒後、ロック所有者が終了すると、待機スレッドが実行されます。

ただし、実際には、両方のスレッドが同期ブロックを同時に実行し、同時に終了します。

期待される出力:

Thread-X <timeX> received the lock.
Thread-X <timeX+5s> exiting...
Thread-Y <timeY> received the lock.
Thread-Y <timeY+5s> exiting...

実際の出力:

Thread-X <time> received the lock.
Thread-Y <time> received the lock.
Thread-X <time+5s> exiting...
Thread-Y <time+5s> exiting...

ここに何かが足りませんか?

import Java.text.SimpleDateFormat;
import Java.util.Date;

public class Test2 {
public static void main(String[] args) {
    MyRunnable m = new MyRunnable();
    Thread t = new Thread(m);
    Thread t1 = new Thread(m);
    t.start();
    t1.start();
    }
}

class MyRunnable implements Runnable {
    @Override
    public void run() {
        synchronized (this) {
            try {
                SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
                Date date = new Date(System.currentTimeMillis());
                System.out.println(Thread.currentThread().getName() + " " + formatter.format(date) + " received the lock.");
                wait(5000);
                date = new Date(System.currentTimeMillis());
                System.out.println(Thread.currentThread().getName() + " " + formatter.format(date) + " exiting...");
            } catch(InterruptedException ie) {}
        }
    }
}
47

答えは Java.lang.Object.wait(long) にあります。

[...]このメソッドにより、現在のスレッド(Tと呼ぶ)がこのオブジェクトの待機セットに自分自身を置き、このオブジェクトのすべての同期要求を放棄します。 [...]

60
Markus

つかいます

Thread.sleep(5000);

Thread.sleepのJavaDocs:

システムタイマーとスケジューラの精度と精度に応じて、指定されたミリ秒数の間、現在実行中のスレッドをスリープ(一時的に実行を停止)します。スレッドはモニターの所有権を失いません。

32
Selindek

Oracle Tutorials からの次の引用は、状況を説明しています。

waitが呼び出されると、スレッドはロックを解除し、実行を中断します。

また、同じオブジェクトによって保護されているsynchronizedブロックを実行できるスレッドは1つだけです!例でwaitを呼び出すとロックが解除され、別のスレッドがロックを取得できるようになります。

13