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-hant/n/270285.html