juc包下四大並發工具


juc.CountDownLatch 閉鎖

一個線程在等待一組線程后再恢復執行

await()等待其他線程執行完畢

被等待線程執行完畢后計數器-1

如何知道其他線程執行完了?

計數器,若一組線程為,CountDown為5,減到0代表等待線程被全部執行完畢

一次性工具:當Countdown的值減到0的時候再也無法恢復

 

juc內部的代碼都是lock體系來實現的

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;


// 運動員線程
class CDLTask implements Runnable {
    private CountDownLatch countDownLatch;

    public CDLTask(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"開始跑步");
        try {
            TimeUnit.SECONDS.sleep(1);
            System.out.println(Thread.currentThread().getName()+"到達終點");
            countDownLatch.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(4);
        CDLTask cdlTask = new CDLTask(countDownLatch);
        System.out.println("比賽開始...");
        new Thread(cdlTask,"運動員A").start();
        new Thread(cdlTask,"運動員B").start();
        new Thread(cdlTask,"運動員C").start();
        new Thread(cdlTask,"運動員D").start();
        // 等待所有線程都到達終點后再輸出此語句
        countDownLatch.await();
        System.out.println("比賽結束...");
    }
}

 


juc.CyclicBarrier  循環柵欄

一組線程同時到達臨界點后再恢復執行(先到達臨界點的線程會阻塞,直到所有線程都到達臨界點)

public CyclicBarrier(int parties, Runnable barrierAction)

當多個線程同時到達臨界點時,

隨機挑選一個線程執行barrierAction后再同時恢復執行

計數器的值可以恢復

await

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

class CBTask implements Runnable {
    private CyclicBarrier cyclicBarrier;

    public CBTask(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+
                "正在寫入數據...");
        try {
            TimeUnit.SECONDS.sleep(2);
            System.out.println(Thread.currentThread().getName()+
                    "寫入數據完畢,等待其他線程寫入完畢...");
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        System.out.println("所有線程均已寫入完畢,繼續恢復執行...");
    }
}
class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(4
                ,() -> {
            System.out.println("當前線程為:"+Thread.currentThread().getName());
        });
        CBTask cbTask = new CBTask(cyclicBarrier);
        for (int i = 0; i < 4; i++) {
            new Thread(cbTask,"寫線程"+(i+1)).start();
        }
    }
}

 


juc.Exchanger 線程交換器

用於兩個線程直線的數據交換,當Exchanger只有一個線程時,該線程會阻塞直到有別的線程
調用exchange進入緩沖區,當前線程與新線程交換數據后同時恢復執行。
import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;


class ExchangerDemo {
    public static void main(String[] args) {
        Exchanger<String> exchanger = new Exchanger<>();
        Thread girlThread = new Thread(() -> {
            try {
                String girl = exchanger.exchange("我喜歡你.....");
                System.out.println("女生說:"+girl);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        girlThread.start();
        Thread boyThread = new Thread(() -> {
            System.out.println("女神緩緩步入眼簾...");
            try {
                TimeUnit.SECONDS.sleep(1);
                String boy = exchanger.exchange("我喜歡你!");
                System.out.println("男生說:"+boy);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        boyThread.start();
    }
}
 
        

 



juc.Semaphore 信號量

acquire() : 嘗試占用一個信號量,失敗的線程會阻塞直到有新的信號量

release() : 釋放一個信號量

acquire(int n) : 嘗試占用n個信號量,失敗的線程會阻塞直到有新的信號量

release(int n) : 釋放n個信號量

 

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;


class SemaphoreTask implements Runnable {
    private Semaphore semaphore;

    public SemaphoreTask(Semaphore semaphore) {
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        try {
            semaphore.acquire(2);
            System.out.println(Thread.currentThread()
                    .getName()+"占用2台設備生產");
            TimeUnit.SECONDS.sleep(2);
            System.out.println(Thread.currentThread()
                    .getName()+"生產完畢,釋放設備");
            semaphore.release(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(5);
        SemaphoreTask task = new SemaphoreTask(semaphore);
        for (int i = 0; i < 8; i++) {
            new Thread(task,"工人"+(i+1)).start();
        }
    }
}

 這里有一篇比較好的博客關於cyclicbarrier和countdownlatch的區別:

https://blog.csdn.net/liangyihuai/article/details/83106584


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM