您好,登錄后才能下訂單哦!
如何深入理解Java多線程與并發框中的并發輔助工具類,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
使用場景:用于 有且僅有兩個線程 間的 數據傳輸,就就是線程間的 通信 。它是 生產者/消費者 d的 wait() / notify() 的最佳替代工具。 核心原理:方法 exchange()阻塞特性:此方法被調用后等待其他線程來取數據,如果沒有其他線程取得數據,則一直 阻塞。
示例:交替打印奇偶數:
public class Print { public static void main(String[] args) { // 交換器 Exchanger<Integer> exchanger = new Exchanger<>(); // 起始打印數值 Integer startNumber = 1; // 終止的數值 Integer endNumber= 100; // 線程1 Thread t1 = new Thread(new Thread1(exchanger, startNumber, endNumber)); Thread t2 = new Thread(new Thread2(exchanger, startNumber, endNumber)); // 設置線程名稱 t1.setName("thread-no-1"); t2.setName("thread-no-2"); // 啟動線程 t1.start(); t2.start(); } } /** * 打印奇數的線程 */ class Thread1 implements Runnable { private Exchanger<Integer> exchanger; /** 被打印的數 */ private Integer number; private final Integer endNumber; public Thread1(Exchanger<Integer> exchanger, Integer startNumber, Integer endNumber) { this.exchanger = exchanger; this.number = startNumber; this.endNumber = endNumber; } @Override public void run() { while (number <= endNumber) { if (number % 2 == 1) { System.out.println("線程:" + Thread.currentThread().getName() + " : " + number); } try { exchanger.exchange(number++); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * 打印偶數的線程 */ class Thread2 implements Runnable { private Exchanger<Integer> exchanger; /** 被打印的數 */ private Integer number; private final Integer endNumber; public Thread2(Exchanger<Integer> exchanger, Integer startNumber, Integer endNumber) { this.exchanger = exchanger; this.number = startNumber; this.endNumber = endNumber; } @Override public void run() { while (number <= endNumber) { if (number % 2 == 0) { System.out.println("線程:" + Thread.currentThread().getName() + " : " + number); } try { exchanger.exchange(number++); } catch (InterruptedException e) { e.printStackTrace(); } } } }
核心原理: 通過發放設置最大 許可數,來限制線程的并發數。 默認是 非公平鎖,效率高。
public Semaphore(int permits) { sync = new NonfairSync(permits); } Semaphore semaphore = new Semaphore(5); try { semaphore.acquire(); // 獲取許可 // 邏輯 } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); // 釋放許可 }
核心原理:線程以 組團 的方式進行任務。 count 作為 stat 狀態。await() 方式將 阻塞當前線程,直到 count 為 0。
CountDownLatch countDownLatch = new CountDownLatch(5); countDownLatch.countDown(); // count - 1 // 預處理 try { countDownLatch.await(); // 阻塞當前線程 // 大家一起處理的時候,我才處理 } catch (InterruptedException e) { e.printStackTrace(); }
Sync同步器
private static final class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 4982264981922014374L; Sync(int count) { setState(count); } int getCount() { return getState(); } protected int tryAcquireShared(int acquires) { return (getState() == 0) ? 1 : -1; } protected Boolean tryReleaseShared(int releases) { // 遞減 count; 轉換為零時發出信號 for (;;) { int c = getState(); if (c == 0) return false; int nextc = c-1; if (compareAndSetState(c, nextc)) return nextc == 0; } } }
核心原理: 基于 ReentrantLock 和 Condition。 CyclicBarrier 不僅具有 CountDownLatch 的功能,還有實現屏障等待的功能,也就是階段性同步。
CyclicBarrier與CountDownLatch比較
CountDownLatch:一個線程(或者多個),等待另外N個線程完成某個事情之后才能執行;CyclicBarrier:N個線程相互等待,任何一個線程完成之前,所有的線程都必須等待。
CountDownLatch:一次性的;CyclicBarrier:可以重復使用。
CountDownLatch基于AQS;CyclicBarrier基于鎖和Condition。本質上都是依賴于volatile和CAS實現的。
看完上述內容,你們掌握如何深入理解Java多線程與并發框中的并發輔助工具類的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。