問題:現在有T1、T2、T3三個執行緒,你怎樣保證T2在T1執行完后執行,T3在T2執行完后執行
實作:使用Thread中的join方法實作
分析:
Thread類中的join方法是用來同步的,底層其實是呼叫了wait方法,先來看一下演示代碼:
package com.whh.concurrency;
/**
*@description:
* 問題:現在有 T1、T2、T3 三個執行緒,怎樣保證 T2 在 T1 執行完后執行T3在T2執行完
* 分析:使用join方法實作
*@author:wenhuohuo
*/
public class MyJoin {
public static void main(String[] args) {
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("執行緒1");
}
},"t1");
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
t1.join();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("執行緒2");
}
},"t2");
final Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
t2.join();
}catch (Exception e){
e.printStackTrace();
}
System.out.println("執行緒3");
}
},"t3");
t3.start();
t2.start();
t1.start();
}
}
執行結果:
執行緒1
執行緒2
執行緒3
可以看到,我們讓t2執行緒呼叫t1.join,t3呼叫t2.join,盡管是t3,t2,t1分別start,執行順序還是t1,t2,t3,是因為join方法底層使用的是wait方法,
- 查看
join方法原始碼
public final void join() throws InterruptedException {
join(0); //傳入的是毫秒值
}
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()) { //isAlive()是native方法,判斷執行緒是否還存活
wait(0); //wait(0),不計時間,一直等待,直到有notify()或notifyAll()來喚醒,
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);//傳入時間,表示在時間值消耗完之前一直等待,直到過了等待時間,
now = System.currentTimeMillis() - base;
}
}
}
1)從原始碼中,我們結合之前的代碼分析,t2.join()和t3.join(),均沒有傳值,相當于join(0),表示不計時間,t2會一直wait等待t1執行完成,t3會一直wait等待t2執行完成,所以執行結果順序是t3,t2,t1,
2)當傳入的毫秒值不為0時,就一直回圈等待,直到過了等待時間(dalay<=0),則執行break方法,那么將不再等待,
- 改變
join()傳入的毫秒值,查看執行順序并分析結果:
public class MyJoin {
public static void main(String[] args) {
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
//處理業務時間,模擬為8秒
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("執行緒1");
}
},"t1");
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
t1.join(4000); //t2等待t1執行緒4秒
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("執行緒2");
}
},"t2");
final Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
t2.join(2000); //t3等待t2執行緒2秒
}catch (Exception e){
e.printStackTrace();
}
System.out.println("執行緒3");
}
},"t3");
t3.start();
t2.start();
t1.start();
}
}
執行結果:
執行緒3 //程式啟動過了2秒執行t3
執行緒2 //過了4秒執行t2
執行緒1 //過了8秒執行t1
分析:我們讓t1 睡眠8秒模擬業務執行時間,t2等待t1 的時間為4秒,t3等待t2的時間為2秒,那么當t1,t2,t3啟動后,等待的時間,t3會因為t2的等待時間4秒太長而先與t2執行,t2會因為t1的8秒太長而先與t1執行,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/192020.html
標籤:其他
下一篇:Centos7安裝Tomcat
