web-dev-qa-db-ja.com

このスレッド参加コードはどういう意味ですか?

このコードでは、2つの結合と中断はどういう意味ですか? t1.join()は、t2が終了するまでt1を停止させますか?

Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread t2 = new Thread(new EventThread("e2"));
t2.start();
while (true) {
   try {
      t1.join();
      t2.join();
      break;
   } catch (InterruptedException e) {
      e.printStackTrace();
   }
}
147
user697911

Thread.join()メソッドjavadocs から引用するには:

join()このスレッドが終了するのを待ちます。

サンプルコードを実行しているスレッドがあります。これはおそらく メインスレッド です。

  1. メインスレッドはt1スレッドとt2スレッドを作成して起動します。 2つのスレッドは並行して実行を開始します。
  2. メインスレッドはt1.join()を呼び出して、t1スレッドが終了するのを待ちます。
  3. t1スレッドが完了し、t1.join()メソッドがメインスレッドに戻ります。 t1は、join()呼び出しが行われる前に既に終了している可能性があることに注意してください。その場合、join()呼び出しはすぐに戻ります。
  4. メインスレッドはt2.join()を呼び出して、t2スレッドが終了するのを待ちます。
  5. t2スレッドが完了し(またはt1スレッドが完了する前に完了した可能性があります)、t2.join()メソッドがメインスレッドに戻ります。

t1スレッドとt2スレッドは並行して実行されていますが、それらを開始したメインスレッドはそれが完了するまで待つ必要があることを理解することが重要です。続けることができます。それは一般的なパターンです。また、t1および/またはt2が終了した可能性がありますbeforeメインスレッドはそれらに対してjoin()を呼び出します。もしそうなら、join()は待たずにすぐに戻ります。

t1.join()は、t1が終了するまでt2を停止させることを意味しますか?

いいえ。t1.join()を呼び出しているmainスレッドは実行を停止し、t1スレッドが終了するのを待ちます。 t2スレッドは並行して実行されており、t1またはt1.join()呼び出しの影響を受けません。

Try/catchの観点では、join()InterruptedExceptionをスローします。これは、join()を呼び出しているメインスレッド自体が別のスレッドによって割り込まれる可能性があることを意味します。

while (true) {

whileループで結合を持つのは奇妙なパターンです。通常、最初の結合を実行し、次に2番目の結合を実行して、それぞれの場合に適切にInterruptedExceptionを処理します。ループに入れる必要はありません。

284
Gray

これはJavaのお気に入りのインタビューの質問です。

Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread e2 = new Thread(new EventThread("e2"));
t2.start();

while (true) {
    try {
        t1.join(); // 1
        t2.join(); // 2  These lines (1,2) are in in public static void main
        break;
    }
}

t1.join()は、t1が "最初に終了したい"のようなものであることを意味します。 t2の場合も同様です。誰がt1またはt2スレッド(この場合はmainメソッド)を開始したとしても、mainはt1t2がタスクを終了するまで待ちます。

ただし、t1およびt2自体結合呼び出しの順序に関係なく並行して実行できますt1およびt2では、注意が必要です。 waitが必要なのはmain/daemonスレッドです。

65
AmitG

join()はスレッドが完了するのを待つことを意味します。これはブロッカーメソッドです。メインスレッド(join()を実行するスレッド)は、t1がその作業を終了するまでt1.join()行を待機し、それからt2.join()についても同じ処理を行います。

43
Avi

絵は千語の価値があります。

    Main thread-->----->--->-->--block##########continue--->---->
                 \                 |               |
sub thread start()\                | join()        |
                   \               |               |
                    ---sub thread----->--->--->--finish    

もっと詳しく知りたい場合は をクリックしてください

17
xxy

スレッドtAがtB.join()を呼び出すと、その原因はtBが死ぬのを待つかtA自身が中断されるだけでなく、tBの最後のステートメントとtBスレッドのtB.join()の後の次のステートメントの間にビフォアビフォアリレーションを作成します。

スレッド内のすべてのアクションは、他のスレッドがそのスレッドのjoin()から正常に戻る前に発生します。

番組という意味

class App {
    // shared, not synchronized variable = bad practice
    static int sharedVar = 0;
    public static void main(String[] args) throws Exception {
        Thread threadB = new Thread(() -> {sharedVar = 1;});
        threadB.start();
        threadB.join();

        while (true) 
            System.out.print(sharedVar);
    }
}

常に印刷する

>> 1111111111111111111111111 ...

でも番組

class App {
    // shared, not synchronized variable = bad practice
    static int sharedVar = 0;
    public static void main(String[] args) throws Exception {
        Thread threadB = new Thread(() -> {sharedVar = 1;});
        threadB.start();
        // threadB.join();  COMMENT JOIN

        while (true)
            System.out.print(sharedVar);
    }
}

印刷できるだけでなく

>> 0000000000 ... 000000111111111111111111111111 ...

しかし

>> 00000000000000000000000000000000000000000000 ... 

常に '0'のみ.

Java Memory Modelは、「共有する」の新しい値をthreadBからメインスレッドに移す前に関係なく(スレッド開始、スレッド結合、「synchonized」キーワードの使用、AtomicXXX変数の使用など)必要としないためです。

8
Ivan Golovach

Oracleのドキュメントから Joinsのページ

joinメソッドを使用すると、あるスレッドが別のスレッドの完了を待つことができます。

T1が、現在スレッドが実行されているThreadオブジェクトの場合、

t1.join() : causes the current thread to pause execution until t1's thread terminates.

T2が、そのスレッドが現在実行中のThreadオブジェクトである場合、

t2.join(); causes the current thread to pause execution until t2's thread terminates.

join APIは低レベルのAPIで、以前のバージョンのJavaで導入されました。並行処理の面で多くのことが一定期間にわたって変更されました(特にjdk 1.5リリースで)。

Java.util.concurrent APIでも同じことができます。いくつかの例は

  1. ExecutorServiceinvokeAll を使用する
  2. CountDownLatch を使う
  3. ExecutorsForkJoinPool または newWorkStealingPool を使用する(Java 8以降)

関連するSEの質問を参照してください。

すべてのスレッドがJavaでの作業を終了するまで待ちます

2
Ravindra babu

簡単に言えば:
t1.join()は、t1が完了した後に戻ります。
スレッドt1には、それが終了するのを待つ以外は何もしません。
当然のことながら、t1.join()に続くコードはt1.join()が戻った後にのみ実行されます。

2
c0der

私にとって、Join()の振る舞いは、誰が誰を待っているのか覚えているので常に混乱していました。そのように覚えようとしないでください。

その下は純粋なwait()とnotify()メカニズムです。

私たちはみんな、すべてのオブジェクトに対してwait()を呼び出すと(t1)、呼び出し元のオブジェクト(main)が待合室に送られる(Blocked状態)ことを知っています。

ここでは、メインスレッドがjoin()を呼び出しています。これは、カバーの下でwait()です。そのため、メインスレッドは通知があるまで待機します。実行が完了すると(スレッド完了)、t1によって通知が出されます。

通知を受け取った後、mainは待合室を出て実行に進みます。

0
Arjun Patil

それが役に立てば幸い!

package join;

public class ThreadJoinApp {

    Thread th = new Thread("Thread 1") {
        public void run() {
            System.out.println("Current thread execution - " + Thread.currentThread().getName());
            for (int i = 0; i < 10; i++) {
                System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
            }
        }
    };

    Thread th2 = new Thread("Thread 2") {
        public void run() {
            System.out.println("Current thread execution - " + Thread.currentThread().getName());

            //Thread 2 waits until the thread 1 successfully completes.
            try {
            th.join();
            } catch( InterruptedException ex) {
                System.out.println("Exception has been caught");
            }

            for (int i = 0; i < 10; i++) {
                System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
            }
        }
    };

    public static void main(String[] args) {
        ThreadJoinApp threadJoinApp = new ThreadJoinApp();
        threadJoinApp.th.start();
        threadJoinApp.th2.start();
    }

    //Happy coding -- Parthasarathy S
}
0
Parthasarathy S