Java線程通訊的實現(xiàn)方法總結(jié)
線程通訊指的是多個線程之間通過共享內(nèi)存或消息傳遞等方式來協(xié)調(diào)和同步它們的執(zhí)行。在多線程編程中,通常會出現(xiàn)多個線程需要共同完成某個任務(wù)的情況,這時就需要線程之間進行通訊,以保證任務(wù)能夠順利地執(zhí)行。
線程通訊的實現(xiàn)方式主要有以下兩種:
共享內(nèi)存:多個線程可以訪問同一個共享內(nèi)存區(qū)域,通過讀取和寫入內(nèi)存中的數(shù)據(jù)來進行通訊和同步。
消息傳遞:多個線程之間通過消息隊列、管道、信號量等機制來傳遞信息和同步狀態(tài)。
常見場景
線程通訊的常見場景有以下幾個:
多個線程共同完成某個任務(wù):例如一個爬蟲程序需要多個線程同時抓取不同的網(wǎng)頁,然后將抓取結(jié)果合并保存到數(shù)據(jù)庫中。這時需要線程通訊來協(xié)調(diào)各個線程的執(zhí)行順序和共享數(shù)據(jù)。
避免資源沖突:多個線程訪問共享資源時可能會引發(fā)競爭條件,例如多個線程同時讀寫一個文件或數(shù)據(jù)庫。這時需要線程通訊來同步線程之間的數(shù)據(jù)訪問,避免資源沖突。
保證順序執(zhí)行:在某些情況下,需要保證多個線程按照一定的順序執(zhí)行,例如一個多線程排序算法。這時需要線程通訊來協(xié)調(diào)各個線程的執(zhí)行順序。
線程之間的互斥和同步:有些場景需要確保只有一個線程能夠訪問某個共享資源,例如一個計數(shù)器。這時需要使用線程通訊機制來實現(xiàn)線程之間的互斥和同步。
實現(xiàn)方法
線程通訊的實現(xiàn)方法有以下幾種:
等待和通知機制:使用 Object 類的 wait() 和 notify() 方法來實現(xiàn)線程之間的通訊。當一個線程需要等待另一個線程執(zhí)行完某個操作時,它可以調(diào)用 wait() 方法使自己進入等待狀態(tài),同時釋放占有的鎖,等待其他線程調(diào)用 notify() 或 notifyAll() 方法來喚醒它。被喚醒的線程會重新嘗試獲取鎖并繼續(xù)執(zhí)行。
信號量機制:使用 Java 中的 Semaphore 類來實現(xiàn)線程之間的同步和互斥。Semaphore 是一個計數(shù)器,用來控制同時訪問某個資源的線程數(shù)。當某個線程需要訪問共享資源時,它必須先從 Semaphore 中獲取一個許可證,如果已經(jīng)沒有許可證可用,線程就會被阻塞,直到其他線程釋放了許可證。
柵欄機制:使用 Java 中的 CyclicBarrier 類來實現(xiàn)多個線程之間的同步,它允許多個線程在指定的屏障處等待,并在所有線程都達到屏障時繼續(xù)執(zhí)行。
鎖機制:使用 Java 中的 Lock 接口和 Condition 接口來實現(xiàn)線程之間的同步和互斥。Lock 是一種更高級的互斥機制,它允許多個條件變量(Condition)并支持在同一個鎖上等待和喚醒。
具體代碼實現(xiàn)
等待通知實現(xiàn)
以下是一個簡單的 wait() 和 notify() 方法的等待通知示例:
public class WaitNotifyDemo { public static void main(String[] args) { Object lock = new Object(); ThreadA threadA = new ThreadA(lock); ThreadB threadB = new ThreadB(lock); threadA.start(); threadB.start(); } static class ThreadA extends Thread { private Object lock; public ThreadA(Object lock) { this.lock = lock; } public void run() { synchronized (lock) { System.out.println("ThreadA start..."); try { lock.wait(); // 線程A等待 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("ThreadA end..."); } } } static class ThreadB extends Thread { private Object lock; public ThreadB(Object lock) { this.lock = lock; } public void run() { synchronized (lock) { System.out.println("ThreadB start..."); lock.notify(); // 喚醒線程A System.out.println("ThreadB end..."); } } } }
在這個示例中,定義了一個共享對象 lock,ThreadA 線程先獲取 lock 鎖,并調(diào)用 lock.wait() 方法進入等待狀態(tài)。ThreadB 線程在獲取 lock 鎖之后,調(diào)用 lock.notify() 方法喚醒 ThreadA 線程,然后 ThreadB 線程執(zhí)行完畢。
運行以上程序的執(zhí)行結(jié)果如下:
ThreadA start...
ThreadB start...
ThreadB end...
ThreadA end...
信號量實現(xiàn)
在 Java 中使用 Semaphore 實現(xiàn)信號量,Semaphore 是一個計數(shù)器,用來控制同時訪問某個資源的線程數(shù)。當某個線程需要訪問共享資源時,它必須先從 Semaphore 中獲取一個許可證,如果已經(jīng)沒有許可證可用,線程就會被阻塞,直到其他線程釋放了許可證。它的示例代碼如下:
import java.util.concurrent.Semaphore; public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore = new Semaphore(2); for (int i = 0; i < 5; i++) { new Thread(new Worker(i, semaphore)).start(); } } static class Worker implements Runnable { private int id; private Semaphore semaphore; public Worker(int id, Semaphore semaphore) { this.id = id; this.semaphore = semaphore; } @Override public void run() { try { semaphore.acquire(); System.out.println("Worker " + id + " acquired permit."); Thread.sleep(1000); System.out.println("Worker " + id + " released permit."); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
在這個示例中,創(chuàng)建了一個 Semaphore 對象,并且設(shè)置了許可數(shù)為 2。然后創(chuàng)建了 5 個 Worker 線程,每個 Worker 線程需要獲取 Semaphore 的許可才能執(zhí)行任務(wù)。每個 Worker 線程在執(zhí)行任務(wù)之前先調(diào)用 semaphore.acquire() 方法獲取許可,如果沒有許可則會阻塞,直到 Semaphore 釋放許可。執(zhí)行完任務(wù)之后調(diào)用 semaphore.release() 方法釋放許可。 運行以上程序的執(zhí)行結(jié)果如下:
Worker 0 acquired permit.
Worker 1 acquired permit.
Worker 1 released permit.
Worker 0 released permit.
Worker 2 acquired permit.
Worker 3 acquired permit.
Worker 2 released permit.
Worker 4 acquired permit.
Worker 3 released permit.
Worker 4 released permit.
柵欄實現(xiàn)
在 Java 中,可以使用 CyclicBarrier 或 CountDownLatch 來實現(xiàn)線程的同步,它們兩個使用類似,接下來我們就是 CyclicBarrier 來演示一下線程的同步,CyclicBarrier 的示例代碼如下:
import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class CyclicBarrierDemo { public static void main(String[] args) { CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() { @Override public void run() { System.out.println("All threads have reached the barrier."); } }); for (int i = 1; i <= 3; i++) { new Thread(new Worker(i, cyclicBarrier)).start(); } } static class Worker implements Runnable { private int id; private CyclicBarrier cyclicBarrier; public Worker(int id, CyclicBarrier cyclicBarrier) { this.id = id; this.cyclicBarrier = cyclicBarrier; } @Override public void run() { try { System.out.println("Worker " + id + " is working."); Thread.sleep((long) (Math.random() * 2000)); System.out.println("Worker " + id + " has reached the barrier."); cyclicBarrier.await(); System.out.println("Worker " + id + " is continuing the work."); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } } } }
在這個示例中,創(chuàng)建了一個 CyclicBarrier 對象,并且設(shè)置了參與線程數(shù)為 3。然后創(chuàng)建了 3 個 Worker 線程,每個 Worker 線程會先執(zhí)行一些任務(wù),然后等待其他線程到達 Barrier。所有線程都到達 Barrier 之后,Barrier 會釋放所有線程并執(zhí)行設(shè)置的 Runnable 任務(wù)。 運行以上程序的執(zhí)行結(jié)果如下:
Worker 2 is working.
Worker 3 is working.
Worker 1 is working.
Worker 3 has reached the barrier.
Worker 1 has reached the barrier.
Worker 2 has reached the barrier.
All threads have reached the barrier.
Worker 2 is continuing the work.
Worker 3 is continuing the work.
Worker 1 is continuing the work.
從以上執(zhí)行結(jié)果可以看出,CyclicBarrier 保證了所有 Worker 線程都到達 Barrier 之后才能繼續(xù)執(zhí)行后面的任務(wù),這樣可以保證線程之間的同步和協(xié)作。在本示例中,所有線程都在 Barrier 處等待了一段時間,等所有線程都到達 Barrier 之后才繼續(xù)執(zhí)行后面的任務(wù)。
鎖機制實現(xiàn)
以下是一個使用 Condition 的示例:
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ConditionDemo { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); private volatile boolean flag = false; public static void main(String[] args) { ConditionDemo demo = new ConditionDemo(); new Thread(demo::waitCondition).start(); new Thread(demo::signalCondition).start(); } private void waitCondition() { lock.lock(); try { while (!flag) { System.out.println(Thread.currentThread().getName() + " is waiting for signal."); condition.await(); } System.out.println(Thread.currentThread().getName() + " received signal."); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } private void signalCondition() { lock.lock(); try { Thread.sleep(3000); // 模擬等待一段時間后發(fā)送信號 flag = true; System.out.println(Thread.currentThread().getName() + " sends signal."); condition.signalAll(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } }
在這個示例中,創(chuàng)建了一個 Condition 對象和一個 Lock 對象,然后創(chuàng)建了兩個線程,一個線程等待 Condition 信號,另一個線程發(fā)送 Condition 信號。
等待線程在獲得鎖后,判斷標志位是否為 true,如果為 false,則等待 Condition 信號;如果為 true,則繼續(xù)執(zhí)行后面的任務(wù)。
發(fā)送線程在獲得鎖后,等待一段時間后,將標志位設(shè)置為 true,并且發(fā)送 Condition 信號。 運行以上程序的執(zhí)行結(jié)果如下:
Thread-0 is waiting for signal.
Thread-1 sends signal.
Thread-0 received signal.
從上面執(zhí)行結(jié)果可以看出,等待線程在等待 Condition 信號的時候被阻塞,直到發(fā)送線程發(fā)送了 Condition 信號,等待線程才繼續(xù)執(zhí)行后面的任務(wù)。Condition 對象提供了一種更加靈活的線程通信方式,可以精確地控制線程的等待和喚醒。
小結(jié)
線程通訊指的是多個線程之間通過共享內(nèi)存或消息傳遞等方式來協(xié)調(diào)和同步它們的執(zhí)行,它的實現(xiàn)方法有很多:比如 wait() 和 notify() 的等待和通知機制、Semaphore 信號量機制、CyclicBarrier 柵欄機制,以及 Condition 的鎖機制等。
以上就是Java線程通訊的實現(xiàn)方式總結(jié)的詳細內(nèi)容,更多關(guān)于Java線程通訊的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springcloud結(jié)合bytetcc實現(xiàn)數(shù)據(jù)強一致性原理解析
這篇文章主要介紹了springcloud結(jié)合bytetcc實現(xiàn)數(shù)據(jù)強一致性原理解析,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03SpringBoot打包發(fā)布到linux上(centos 7)的步驟
這篇文章主要介紹了SpringBoot打包發(fā)布到linux上(centos 7)的步驟,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下2020-12-12在RedHat系統(tǒng)上安裝JDK與Tomcat的步驟
這篇文章主要介紹了在RedHat系統(tǒng)上安裝Java與Tomcat的步驟,同樣適用于CentOS等RedHat系的Linux系統(tǒng),需要的朋友可以參考下2015-11-11Spring Security實現(xiàn)驗證碼登錄功能
這篇文章主要介紹了Spring Security實現(xiàn)驗證碼登錄功能,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-01-01Spring Cloud Stream如何實現(xiàn)服務(wù)之間的通訊
這篇文章主要介紹了Spring Cloud Stream如何實現(xiàn)服務(wù)之間的通訊,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-10-10