このコードでは、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();
}
}
Thread.join()
メソッドjavadocs から引用するには:
join()
このスレッドが終了するのを待ちます。
サンプルコードを実行しているスレッドがあります。これはおそらく メインスレッド です。
t1
スレッドとt2
スレッドを作成して起動します。 2つのスレッドは並行して実行を開始します。t1.join()
を呼び出して、t1
スレッドが終了するのを待ちます。t1
スレッドが完了し、t1.join()
メソッドがメインスレッドに戻ります。 t1
は、join()
呼び出しが行われる前に既に終了している可能性があることに注意してください。その場合、join()
呼び出しはすぐに戻ります。t2.join()
を呼び出して、t2
スレッドが終了するのを待ちます。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
を処理します。ループに入れる必要はありません。
これは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はt1
とt2
がタスクを終了するまで待ちます。
ただし、t1
およびt2
自体結合呼び出しの順序に関係なく並行して実行できますt1
およびt2
では、注意が必要です。 waitが必要なのはmain/daemon
スレッドです。
join()
はスレッドが完了するのを待つことを意味します。これはブロッカーメソッドです。メインスレッド(join()
を実行するスレッド)は、t1
がその作業を終了するまでt1.join()
行を待機し、それからt2.join()
についても同じ処理を行います。
絵は千語の価値があります。
Main thread-->----->--->-->--block##########continue--->---->
\ | |
sub thread start()\ | join() |
\ | |
---sub thread----->--->--->--finish
もっと詳しく知りたい場合は をクリックしてください
スレッドtAがtB.join()を呼び出すと、その原因はtBが死ぬのを待つかtA自身が中断されるだけでなく、tBの最後のステートメントとtBスレッドのtB.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変数の使用など)必要としないためです。
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でも同じことができます。いくつかの例は
ExecutorService
で invokeAll を使用するExecutors
の ForkJoinPool または newWorkStealingPool を使用する(Java 8以降)関連するSEの質問を参照してください。
簡単に言えば:t1.join()
は、t1
が完了した後に戻ります。
スレッドt1
には、それが終了するのを待つ以外は何もしません。
当然のことながら、t1.join()
に続くコードはt1.join()
が戻った後にのみ実行されます。
私にとって、Join()の振る舞いは、誰が誰を待っているのか覚えているので常に混乱していました。そのように覚えようとしないでください。
その下は純粋なwait()とnotify()メカニズムです。
私たちはみんな、すべてのオブジェクトに対してwait()を呼び出すと(t1)、呼び出し元のオブジェクト(main)が待合室に送られる(Blocked状態)ことを知っています。
ここでは、メインスレッドがjoin()を呼び出しています。これは、カバーの下でwait()です。そのため、メインスレッドは通知があるまで待機します。実行が完了すると(スレッド完了)、t1によって通知が出されます。
通知を受け取った後、mainは待合室を出て実行に進みます。
それが役に立てば幸い!
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
}