さて、前回の記事では、スレッドの作成と操作について予備的に理解しているので、キーワード結合について話しましょう。
Javaスレッドに少し精通しているパートナーは、Synchronizedがロックを追加して、マルチスレッドがリソースをプリエンプトするのを防ぎ、データセキュリティを向上させることができることを知っています。もちろん、Synchronizedについて言及するときは、参加、待機、通知などについて考えることもできます。
最初に参加について話しましょう。この言葉は誰にでもよく知られています。つまり、;参加;参加;のメンバーになることを意味します。
プログラムを見てみましょう。
package com.example.thread;
public class MyThreadPool {
public static void main(String[] args) throws Exception {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程一开始"+Thread.currentThread());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程一结束"+Thread.currentThread());
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程二开始"+Thread.currentThread());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程二结束"+Thread.currentThread());
}
});
System.out.println("main 方法开始。。。。"+Thread.currentThread());
thread1.start();
thread2.start();
// thread1.join();
// thread2.join();
System.out.println("main 方法结束。。。。"+Thread.currentThread());
}
}
以下の操作の結果を見てみましょう。
main 方法开始。。。。Thread[main,5,main]
main 方法结束。。。。Thread[main,5,main]
线程一开始Thread[Thread-0,5,main]
线程二开始Thread[Thread-1,5,main]
线程一结束Thread[Thread-0,5,main]
线程二结束Thread[Thread-1,5,main]
Process finished with exit code 0
これは問題ありません。メインスレッドは2つのスレッドを追加することで開始され、マルチスレッドは相互に影響を与えることなく実行されます。スレッド1とスレッド2の開始には時間がかかるため、メインスレッドが最初に終了します。次に、スレッド1とスレッド2が開始され、5秒間の待機は明らかに終了します。
結合が追加された場合はどうなりますか?操作の結果を見てみましょう:
main 方法开始。。。。Thread[main,5,main]
线程二开始Thread[Thread-1,5,main]
线程一开始Thread[Thread-0,5,main]
线程二结束Thread[Thread-1,5,main]
线程一结束Thread[Thread-0,5,main]
main 方法结束。。。。Thread[main,5,main]
見てみましょう。メインスレッドを最初に開始してから、スレッド1とスレッド2を開始しても問題ありません。間隔が短すぎて相互に影響を与えないため、最初は最初ではない可能性があります。出力されますが、mainメソッドの前にある必要があります。最初に終了します。どうして?参加してください!スレッド1とスレッド2がjoinメソッドを呼び出すからです!
このプログラムの動作を見てみましょう。最初に、3つのスレッドが互いに影響を与えることなく開始され(joinメソッドが呼び出される前)、次にスレッド1とスレッド2の両方がjoinを呼び出します。最初に、スレッド1がjoinを呼び出し、スレッド1は挟まれています。メインスレッドは最後から始まり、スレッド2の呼び出しが再び結合し、中央にジャンプするため、スレッド2とスレッド1のメソッドが最初に終了します。
なぜですか?
join()のソースコードを見てみましょう。
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
コードから、私たちは見つけることができます。mills == 0の場合、while(isAlive())ループに入ります。つまり、子スレッドが生きている限り、メインスレッドは待機し続けます。
したがって、スレッド1とスレッド2は、実際にはmainメソッドのリソースをプリエンプトし、キューの先頭にジャンプすると、自然に最初に実行を終了します。
さて、今日ここに来て、明日同期を追加しましょう[笑って泣いて]