Java線程等待

Java中線程等待是指讓一個線程等待其它線程完成一定的工作後再執行。Java提供了幾種方式來實現線程等待,包括使用join()方法、wait()和notify()方法、CountDownLatch類、CyclicBarrier類等。本文將會詳細介紹這些方法的使用方法和實例。

一、使用join()方法進行線程等待

join()方法是Thread類提供的一個實例方法,它允許一個線程等待另一個線程的完成。當調用某個線程的join()方法時,當前線程會暫停執行,直到被調用線程執行完畢,當前線程才會繼續執行。如果被調用線程在join()方法調用前已經執行完畢,那麼該方法會立即返回。

下面是一個使用join()方法的示例:

Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("子線程開始執行");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("子線程執行完畢");
    }
});

thread.start();

System.out.println("主線程開始執行");

try {
    thread.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}

System.out.println("主線程執行完畢");

在上述示例中,我們創建了一個新的線程,該線程會等待5秒後執行完畢。在主線程中,我們調用了thread.join()方法,因此主線程會等待子線程執行完畢後再繼續執行。輸出結果如下:

主線程開始執行
子線程開始執行
子線程執行完畢
主線程執行完畢

二、使用wait()和notify()方法進行線程等待

wait()和notify()方法是Object類提供的實例方法,它們可以實現線程間的等待和喚醒。當一個線程執行wait()方法時,它會釋放它所持有的鎖,並進入等待狀態,直到其它線程調用notify()方法或notifyAll()方法來喚醒它。當一個線程執行notify()方法時,它會喚醒一個正處於等待狀態中的線程(注意是隨機喚醒一個線程),使其繼續執行。

下面是一個使用wait()和notify()方法的示例,該示例演示了如何使用兩個線程交替輸出1到10:

class PrintThread implements Runnable {
    private int num;
    private Object lock;

    public PrintThread(int num, Object lock) {
        this.num = num;
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock) {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + " " + num * 10 + i);
                lock.notify();
                if (i != 9) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

public static void main(String[] args) {
    Object lock = new Object();
    Thread thread1 = new Thread(new PrintThread(1, lock));
    Thread thread2 = new Thread(new PrintThread(2, lock));
    thread1.start();
    thread2.start();
}

在上述示例中,我們創建了兩個線程,分別輸出1到10和11到20。在PrintThread類的run()方法中,我們首先獲取lock對象的鎖,並使用wait()方法使線程進入等待狀態,直到另一個線程調用notify()方法來喚醒它。當一個線程輸出完一行後,使用notify()方法喚醒等待狀態的線程,然後自己進入等待狀態,等待其它線程喚醒。這樣,我們就實現了兩個線程交替輸出1到20。

三、使用CountDownLatch類進行線程等待

CountDownLatch類是在Java 5中引入的,並且它是java.util.concurrent包中的一個類。它是一個同步的輔助類,用來協調多個線程之間的同步。CountDownLatch的功能是阻塞一個線程或多個線程,直到它所計數的線程執行完畢才能向下執行。它使用一個計數器來實現這個功能,計數器初始值為線程數,當某個線程執行完畢時,計數器減1,當計數器減為0時,所有等待該計數器的線程將會被喚醒。

下面是一個使用CountDownLatch類的示例:

public static void main(String[] args) throws InterruptedException {
    int threadCount = 10;
    CountDownLatch latch = new CountDownLatch(threadCount);

    for (int i = 0; i  {
            System.out.println(Thread.currentThread().getName() + " 執行完畢");
            latch.countDown();
        }).start();
    }

    latch.await();

    System.out.println("所有線程執行完畢");
}

在上述示例中,我們使用了一個CountDownLatch對象來等待10個線程執行完畢。當一個線程執行完畢時,我們調用latch.countDown()方法來減少計數器的值,當計數器減為0時,主線程調用latch.await()方法進入等待狀態,直到所有線程執行完畢,主線程才會繼續執行。輸出結果如下:

Thread-0 執行完畢
Thread-1 執行完畢
Thread-3 執行完畢
Thread-2 執行完畢
Thread-4 執行完畢
Thread-8 執行完畢
Thread-9 執行完畢
Thread-5 執行完畢
Thread-7 執行完畢
Thread-6 執行完畢
所有線程執行完畢

四、使用CyclicBarrier類進行線程等待

CyclicBarrier類也是在Java 5中引入的,它也是java.util.concurrent包中的一個類。CyclicBarrier可以被用來協調多個線程之間的同步。它可以讓一組線程在到達某個屏障時被阻塞,直到最後一個線程到達屏障時,所有被阻塞的線程才能繼續執行。CyclicBarrier和CountDownLatch的區別在於,CyclicBarrier可以用於一組線程間相互等待,而CountDownLatch只能用於一個線程等待其它線程執行完畢。

下面是一個使用CyclicBarrier類的示例:

class WorkerThread implements Runnable {
    private String name;
    private CyclicBarrier barrier;

    public WorkerThread(String name, CyclicBarrier barrier) {
        this.name = name;
        this.barrier = barrier;
    }

    @Override
    public void run() {
        try {
            System.out.println(name + " 開始工作");
            Thread.sleep((long) (Math.random() * 5000));
            System.out.println(name + " 工作完畢,等待其它線程");
            barrier.await();
            System.out.println(name + " 繼續執行");
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

public static void main(String[] args) throws InterruptedException {
    int threadCount = 5;
    CyclicBarrier barrier = new CyclicBarrier(threadCount, () -> {
        System.out.println("所有線程工作完畢,開始匯總結果");
    });

    for (int i = 0; i < threadCount; i++) {
        new Thread(new WorkerThread("線程" + i, barrier)).start();
    }

    Thread.sleep(6000);
}

在上述示例中,我們創建了5個線程,它們會隨機工作一段時間後等待其它線程,最後再匯總工作結果。在WorkerThread類的run()方法中,我們使用CyclicBarrier類的await()方法來等待其它線程,當所有線程都到達屏障時,所有線程才能繼續執行。輸出結果如下:

線程0 開始工作
線程2 開始工作
線程4 開始工作
線程3 開始工作
線程1 開始工作
線程2 工作完畢,等待其它線程
線程0 工作完畢,等待其它線程
線程1 工作完畢,等待其它線程
線程3 工作完畢,等待其它線程
線程4 工作完畢,等待其它線程
所有線程工作完畢,開始匯總結果
線程4 繼續執行
線程1 繼續執行
線程0 繼續執行
線程2 繼續執行
線程3 繼續執行

總結

Java中提供了多種方法來實現線程等待,包括使用join()方法、wait()和notify()方法、CountDownLatch類、CyclicBarrier類等。在實際代碼編寫中,我們需要根據具體的需求選擇合適的方式來實現線程等待。無論是哪種方式,它們都可以幫助我們實現線程之間的同步,保證多個線程之間的協作。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/270285.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-16 13:36
下一篇 2024-12-16 13:36

相關推薦

  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java Bean加載過程

    Java Bean加載過程涉及到類加載器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean加載的過程。 一、類加載器 類加載器是Java虛擬機…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發佈。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字符串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字符串中是否存在多個指定字符: 一、字符串遍歷 字符串是Java編程中非常重要的一種數據類型。要判斷字符串中是否存在多個指定字符…

    編程 2025-04-29
  • VSCode為什麼無法運行Java

    解答:VSCode無法運行Java是因為默認情況下,VSCode並沒有集成Java運行環境,需要手動添加Java運行環境或安裝相關插件才能實現Java代碼的編寫、調試和運行。 一、…

    編程 2025-04-29
  • Java任務下發回滾系統的設計與實現

    本文將介紹一個Java任務下發回滾系統的設計與實現。該系統可以用於執行複雜的任務,包括可回滾的任務,及時恢復任務失敗前的狀態。系統使用Java語言進行開發,可以支持多種類型的任務。…

    編程 2025-04-29
  • Java 8 Group By 會影響排序嗎?

    是的,Java 8中的Group By會對排序產生影響。本文將從多個方面探討Group By對排序的影響。 一、Group By的概述 Group By是SQL中的一種常見操作,它…

    編程 2025-04-29

發表回復

登錄後才能評論