第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

多線程 join 方法

1. 前言

本節(jié)對 join 方法進(jìn)行深入的剖析,主要內(nèi)容點(diǎn)如下:

  • 了解 join 方法的作用,初步的理解 join 方法的使用帶來的效果是學(xué)習(xí)本節(jié)內(nèi)容的基礎(chǔ);
  • 了解 join 方法異常處理,我們在使用 join 方法是,需要對 join 方法進(jìn)行有效的異常處理;
  • 通過匿名內(nèi)部類創(chuàng)建Thread 是我們本節(jié)代碼示例所使用的的方式,對這種方式的掌握在后續(xù)工作中非常重要;
  • 掌握 join 方法如何使用,這是本節(jié)的重點(diǎn)內(nèi)容,也是本節(jié)的核心內(nèi)容;
  • 掌握帶參數(shù)的 join 方法使用,在后續(xù)開發(fā)過程中,如果對接口的最大返回時間有要求的話,某些情況下會用到帶參數(shù)的 join 方法,次重點(diǎn)內(nèi)容。

2. join 方法的作用

方法定義:多線程環(huán)境下,如果需要確保某一線程執(zhí)行完畢后才可繼續(xù)執(zhí)行后續(xù)的代碼,就可以通過使用 join 方法完成這一需求設(shè)計。

在項目實踐中經(jīng)常會遇到一個場景,就是需要等待某幾件事情完成后主線程才能繼續(xù)往下執(zhí)行, 比如多個線程加載資源, 需要等待多個線程全部加載完畢再匯總處理。

Thread 類中有一個 join 方法就可以做這個事情,join 方法是 Thread 類直接提供的。join 是無參且返回值為 void 的方法。
圖片描述
如上圖所示,假如有 3 個線程執(zhí)行邏輯,線程 1 需要執(zhí)行5秒鐘,線程 2 需要執(zhí)行10 秒鐘,線程 3 需要執(zhí)行 8 秒鐘。 如果我們的開發(fā)需求是:必須等 3 條線程都完成執(zhí)行之后再進(jìn)行后續(xù)的代碼處理,這時候我們就需要使用到 join 方法。

使用 join 方法后

  • 第 5 秒鐘: 線程 1 執(zhí)行完畢;線程 2 執(zhí)行了一半; 線程 3 還差 3 秒執(zhí)行完畢;
  • 第 8 秒鐘:線程 1 等待了 3 秒; 線程 3 執(zhí)行完畢; 線程 2 還差 2 秒執(zhí)行完畢;
  • 第10 秒鐘: 線程 1 等待了 5 秒; 線程 3 等待了 2 秒;線程 2 執(zhí)行完畢;
  • 從線程 2 執(zhí)行結(jié)束的那一刻:三條線程同時進(jìn)行后續(xù)代碼的執(zhí)行。

這就是 join 方法的作用與解釋。

3. join 方法異常處理

join 方法是 Thread 類中的方法,為了了解該方法的異常處理,我們先來簡要的看下 join 方法的 JDK 源碼:

public final void join() throws InterruptedException {
        join(0);
}

從源代碼中我們可以看到, join 方法拋出了異常:

throws InterruptedException

所以,我們在使用 join 方法的時候,需要對 join 方法的調(diào)用進(jìn)行 try catch 處理或者從方法級別進(jìn)行異常的拋出。

try-catch 處理示例

public class DemoTest implements Runnable{
    @Override
    public void run() {
        System.out.println("線程:"+Thread.currentThread()+" 正在執(zhí)行...");
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(new DemoTest());
        t1. start();
        try {
            t1.join();
        } catch (InterruptedException e) {
            // 異常捕捉處理
        }
    }
}

throws 異常處理示例

public class DemoTest implements Runnable throws InterruptedException {
    @Override
    public void run() {...}
    public static void main(String[] args) {
        Thread t1 = new Thread(new DemoTest());
        t1. start();
        t1.join();
    }
}

4. join 方法如何使用

為了更好的了解 join 方法的使用,我們首先來設(shè)計一個使用的場景。
場景設(shè)計

  • 線程 1 :執(zhí)行時間 5 秒鐘;
  • 線程 2 :執(zhí)行時間 10 秒鐘;
  • 線程 3 :執(zhí)行 8 秒鐘。

需求:我們需要等 3 個線程都執(zhí)行完畢后,再進(jìn)行后續(xù)代碼的執(zhí)行。3 個線程執(zhí)行完畢后,請打印執(zhí)行時間。

期望結(jié)果: 10 秒執(zhí)行時間。
看到這個是不是似曾相識呢? 這就是我們本節(jié)第 2 知識點(diǎn)所舉出的示例,現(xiàn)在我們來進(jìn)行代碼實現(xiàn)和驗證,體會 join 方法的使用。

實例

public class DemoTest{
    public static void main(String[] args) throws InterruptedException {
        Thread threadOne = new Thread(new Runnable() { //線程 1
            @Override
            public void run() {
                try {
                    Thread.sleep (5000 ); //線程 1 休眠 5 秒鐘
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println ("線程 1 休眠 5 秒鐘,執(zhí)行完畢。");
            }
        });

        Thread threadTwo = new Thread(new Runnable() { //線程 2
            ...
                    Thread.sleep (10000 ); //線程 2 修眠 10 秒鐘
            ...
                System.out.println ("線程 2 修眠 10 秒鐘,執(zhí)行完畢。");
            }
        });

        Thread threadThree = new Thread(new Runnable() {//線程 3
            ...
                    Thread.sleep (8000 ); //線程 3 修眠 8 秒鐘
            ...
                System.out.println ("線程 3 修眠 8 秒鐘,執(zhí)行完畢。");
            }
        });

        Long startTime = System.currentTimeMillis();
        threadOne. start();threadTwo. start();threadThree. start();
        System.out.println("等待三個線程全部執(zhí)行完畢再繼續(xù)向下執(zhí)行,我要使用 join 方法了。");
        threadOne.join(); //線程 1 調(diào)用 join 方法
        threadTwo.join(); //線程 2 調(diào)用 join 方法
        threadThree.join(); //線程 3 調(diào)用 join 方法
        Long endTime = System.currentTimeMillis();
        System.out.println("三個線程都執(zhí)行完畢了,共用時: "+ (endTime - startTime) + "毫秒");
    }
}

執(zhí)行結(jié)果驗證

等待三個線程全部執(zhí)行完畢再繼續(xù)向下執(zhí)行,我要使用 join 方法了。
線程 1 休眠 5 秒鐘,執(zhí)行完畢。
線程 3 修眠 8 秒鐘,執(zhí)行完畢。
線程 2 修眠 10 秒鐘,執(zhí)行完畢。
三個線程都執(zhí)行完畢了,共用時: 10002毫秒

從執(zhí)行的結(jié)果來看,與我們對 join 方法的理解和分析完全相符,請同學(xué)也進(jìn)行代碼的編寫和運(yùn)行,加深學(xué)習(xí)印象。

5. 帶參數(shù)的 join 方法使用

除了無參的 join 方法以外, Thread 類還提供了有參 join 方法如下:

public final synchronized void join(long millis)
    throws InterruptedException

該方法的參數(shù) long millis 代表的是毫秒時間。

方法作用描述:等待 millis 毫秒終止線程,假如這段時間內(nèi)該線程還沒執(zhí)行完,也不會再繼續(xù)等待。
結(jié)合上一個知識點(diǎn)的代碼,我們都是調(diào)用的無參 join 方法,現(xiàn)在對上一個知識點(diǎn)代碼進(jìn)行如下調(diào)整:

threadOne.join(); //線程 1 調(diào)用 join 方法
threadTwo.join(3000); //線程 2 調(diào)用 join 方法
threadThree.join(); //線程 3 調(diào)用 join 方法

從代碼中我們看到,線程 2 使用 join 方法 3000 毫秒的等待時間,如果 3000 毫毛后,線程 2 還未執(zhí)行完畢,那么主線程則放棄等待線程 2,只關(guān)心線程 1 和線程 3。

我們來看下執(zhí)行結(jié)果

等待三個線程全部執(zhí)行完畢再繼續(xù)向下執(zhí)行,我要使用 join 方法了。
線程 1 休眠 5 秒鐘,執(zhí)行完畢。
線程 3 修眠 8 秒鐘,執(zhí)行完畢。
三個線程都執(zhí)行完畢了,共用時: 8000毫秒
線程 2 修眠 10 秒鐘,執(zhí)行完畢。

從執(zhí)行結(jié)果來看, 總用時 8000 毫秒,因為線程 2 被放棄等待了,所以只考慮線程 1 和線程 3 的執(zhí)行時間即可。

6. 小結(jié)

在實際的開發(fā)場景中,經(jīng)常會設(shè)計到對 join 方法的使用,無參方法使用更加常見,了解 join 方法的使用非常重要。

本節(jié)重中之重,就是掌握 join 方法的使用,join 方法在后續(xù)的開發(fā)工作中非常關(guān)鍵,很多情況下都會有所使用。