1. 程式人生 > >java中並發包裏面的內容

java中並發包裏面的內容

並發

java中的並發包裏面的內容

1、CyclicBarrier

一個同步輔助類,允許一組線程相互等待,直到這組線程都到達某個公共屏障點。該barrier在釋放等待線程後可以重用,因此稱為循環的barrier。

來個示例:

  • package test;


  • import java.util.concurrent.CyclicBarrier;

  • import java.util.concurrent.ExecutorService;

  • import java.util.concurrent.Executors;


  • public class Recipes_CyclicBarrier {

  • public static CyclicBarrier barrier = new CyclicBarrier(10);


  • public static void main(String[] args){

  • ExecutorService executor = Executors.newCachedThreadPool();//FixedThreadPool(10);

  • for(int i=1;i<=10;i++){

  • executor.submit(new Thread(new Runner(i+"號選手")));

  • }

  • executor.shutdown();

  • }

  • }


  • class Runner implements Runnable{

  • private String name;


  • public Runner(String name){

  • this.name = name;

  • }


  • @Override

  • public void run() {

  • System.out.println(name + "準備好了。");

  • try {

  • Recipes_CyclicBarrier.barrier.await(); //此處就是公共屏障點,所有線程到達之後,會釋放所有等待的線程

  • } catch (Exception e) {

  • }

  • System.out.println(name + "起跑!");

  • }

  • }

  • 2、CountDownLatch

    CountDownLatch和CyclicBarrier有點類似,但是還是有些區別的。CountDownLatch也是一個同步輔助類,它允許一個或者多個線程一直等待,直到正在其他線程中執行的操作完成。它是等待正在其他線程中執行的操作,並不是線程之間相互等待。CountDownLatch初始化時需要給定一個計數值,每個線程執行完之後,必須調用countDown()方法使計數值減1,直到計數值為0,此時等待的線程才會釋放。

    來個示例:

    [java] view plain copy

  • package test;


  • import java.util.concurrent.CountDownLatch;

  • import java.util.concurrent.CyclicBarrier;

  • import java.util.concurrent.ExecutorService;

  • import java.util.concurrent.Executors;


  • public class CountDownLatchDemo {

  • public static CountDownLatch countDownLatch = new CountDownLatch(10);//初始化計數值


  • public static void main(String[] args){

  • ExecutorService executor = Executors.newCachedThreadPool();//FixedThreadPool(10);

  • for(int i=1;i<=10;i++){

  • executor.submit(new Thread(new Runner1(i+"號選手")));

  • }

  • executor.shutdown();

  • }

  • }


  • class Runner1 implements Runnable{

  • private String name;


  • public Runner1(String name){

  • this.name = name;

  • }


  • @Override

  • public void run() {

  • System.out.println(name + "準備好了。");

  • CountDownLatchDemo.countDownLatch.countDown(); //計數值減1

  • try {

  • CountDownLatchDemo.countDownLatch.await();

  • } catch (Exception e) {

  • }

  • System.out.println(name + "起跑!");

  • }

  • }

  • 3、CopyOnWriteArrayList & CopyOnWriteArraySet

    CopyOnWriteArrayList & CopyOnWriteArraySet是並發容器,適合讀多寫少的場景,如網站的黑白名單設置。缺點是內存占用大,數據一致性的問題,CopyOnWrite容器只能保證數據最終的一致性,不能保證數據實時一致性。鑒於它的這些缺點,可以使用ConcurrentHashMap容器。

    實現原理:新增到容器的數據會放到一個新的容器中,然後將原容器的引用指向新容器,舊容器也會存在,因此會有兩個容器占用內存。我們也可以用同樣的方式實現自己的CopyOnWriteMap。

    4、ConcurrentHashMap

    ConcurrentHashMap同樣是一個並發容器,將同步粒度最小化。

    實現原理:ConcurrentHashMap默認是由16個Segment組成,每個Segment由多個Hashtable組成,數據變更需要經過兩次哈希算法,第一次哈希定位到Segment,第二次哈希定位到Segment下的Hashtable,容器只會將單個Segment鎖住,然後操作Segment下的Hashtable,多個Segment之間不受影響。如果需要擴容不是對Segment擴容而是對Segment下的Hashtable擴容。雖然經過兩次哈希算法會使效率降低,但是比鎖住整個容器效率要高得多。

    5、BlockingQueue

    BlockingQueue只是一個接口,它的實現類有ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、DelayQueue、LinkedBlockingDeque。

    ArrayBlockingQueue:由數據支持的有界阻塞隊列。

    LinkedBlockingQueue:基於鏈接節點、範圍任意的阻塞隊列。

    PriorityBlockingQueue:無界阻塞隊列。

    SynchronousQueue:一種阻塞隊列,其中每個插入操作必須等待另一個線程的對應移除操作。

    DelayQueue:Delayed元素的一個無界阻塞隊列。

    LinkedBlockingDeque:基於鏈接節點、範圍任意的雙端阻塞隊列,可以在隊列的兩端添加、移除元素。

    6、Lock

    Lock分為公平鎖和非公平鎖,默認是非公平鎖。實現類有ReetrantLock、ReetrantReadWriteLock,都依賴於AbstractQueuedSynchronizer抽象類。ReetrantLock將所有Lock接口的操作都委派到Sync類上,Sync有兩個子類:NonFairSync和FaiSync,通過其命名就能知道分別處理非公平鎖和公平鎖的。AbstractQueuedSynchronizer把所有請求構成一個CLH隊列,這裏是一個虛擬隊列,當有線程競爭鎖時,該線程會首先嘗試是否能獲取鎖,這種做法對於在隊列中等待的線程來說是非公平的,如果有線程正在Running,那麽通過循環的CAS操作將此線程增加到隊尾,直至添加成功。

    7、Atomic包

    Atomic包下的類實現了原子操作,有對基本類型如int、long、boolean實現原子操作的類:AtomicInteger、AtomicLong、AtomicBoolean,如果需要對一個對象進行原子操作,也有對對象引用進行原子操作的AtomicReference類,還有對對象數組操作的原子類:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。原子操作核心思想是CAS操作,然後調用底層操作系統指令來實現。



java中並發包裏面的內容