1. 程式人生 > >java併發包原理及使用場景

java併發包原理及使用場景

java併發包下有很多內建的處理執行緒安全問題工具類,在集合中就有2種執行緒同步的類,比如:Vector較ArrayList執行緒安全,但是效率較低,同樣的還有Hashtable和HashMap,在實際專案中常用ArrayList與HashMap,因為前者比重,影響執行效率

  • 以下是java的幾種併發包下的使用場景

1.CountDownLatch

CountDownLatch 同步器

1.1 原理:

  • 執行多個或一個執行緒,等待其他多個或一個執行緒執行完畢,在執行當前執行緒
  • java併發包下同步輔助類:定義計數器可以設定個數,每次呼叫countDown() 計數器中的個數就會減1,當計數器的個數等於0的時候,呼叫await方法時,就會執行await方法後面的程式碼,如果計數器個數大於0時,呼叫await時,是不會執行await後面的程式碼

1.2 使用場景:

  • 有一個檔案,需要2個執行緒執行讀寫操作,執行完寫的操作才可以讀取內容 實現:使用計數器CountDownLatch,計數器的個數為2,在每個寫的執行緒執行完畢,呼叫countDown方法,在寫的執行緒後面,呼叫計數器的await方法,await方法後面執行讀執行緒,這樣在讀取資料時,可以保證資料的完整性
public class ThreadWrite implements Runnable {
    private Poeple peo;
    private Integer count;
    private CountDownLatch cdl;

    public ThreadWrite(Poeple peo, Integer count,CountDownLatch cdl) {
        this.peo = peo;
        this.count = count;
        this.cdl = cdl;
    }

    @Override
    public void run() {
            System.out.println("ThreadWrite");
            if (count == 0) {
                peo.setName("小明");
                peo.setSex("男");
            } else if (count == 1) {
                peo.setName("小紅");
                peo.setSex("女");
            }
            cdl.countDown();//每次執行同步器減一
    }
}

public static void main(String[] args) {
    Poeple peo = new Poeple();
    CountDownLatch cdl = new CountDownLatch(2);//建立同步器,執行緒個數為2
    new Thread(new ThreadWrite(peo, 1, cdl)).start();
    new Thread(new ThreadWrite(peo, 1, cdl)).start();
    try {
        cdl.await();//等待同步器個數為0,執行後續程式碼
        new Thread(new ThreadRead(peo)).start();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

2. CyclicBarrier

CyclicBarrier 迴圈屏障

2.1 原理:

  • 執行多個執行緒之間相互等待,執行完畢後在執行執行緒中await後面的程式碼

2.2 使用場景:

  • 多個執行緒在執行計算操作,另一個執行緒需要將計算結果相加,建立一個屏障執行緒,等待其他執行緒執行後在執行屏障執行緒
  • 多個執行緒中有需要全部執行完,最後執行的程式碼
/**
 * 寫執行緒
 */
public class ThreadWrite implements Runnable {
    private Poeple peo;
    private Integer count;
    private CyclicBarrier cb;

    public ThreadWrite(Poeple peo, Integer count, CyclicBarrier cb) {
        this.peo = peo;
        this.count = count;
        this.cb = cb;
    }

    @Override
    public void run() {
        System.out.println("ThreadWrite");
        /*迴圈屏障*/
        try {
            cb.await();//等待執行緒數等於,CyclicBarrier中parties個數,執行之前所有等待執行緒await後面的程式碼
            System.out.println("迴圈屏障");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}


/**
 * 讀取執行緒
 */
public class ThreadRead implements Runnable {
    private Poeple peo;

    public ThreadRead(Poeple peo) {
        this.peo = peo;
    }

    @Override
    public void run() {
        synchronized (peo) {
            System.out.println("ThreadRead");
            System.out.println(peo.getName());
            System.out.println(peo.getSex());
        }
    }
}

public static void main(String[] args) {
        CyclicBarrier cb = new CyclicBarrier(4);//迴圈屏障
        System.out.println("當前執行緒數"+cb.getParties());
        System.out.println("當前執行緒等待數"+cb.getNumberWaiting());
        Poeple peo = new Poeple();
        int count = 0;
        new Thread(new ThreadWrite(peo, count,cb)).start();
        new Thread(new ThreadWrite(peo, count,cb)).start();
        new Thread(new ThreadWrite(peo, count,cb)).start();
        new Thread(new ThreadWrite(peo, count,cb)).start();
}

3. Semaphore

Semaphore:訊號量

3.1 原理:

  • java併發包下,可以處理一個及以上的執行緒的併發量

3.2 使用場景:

  • 一個樓層,有2個入口,一個入口每次只能進1個人,每次可以進2個人,而使用synchronized,只有一個入口,每次只能進1個人,使用訊號量可以提高處理併發的個數
public class ThreadWrite implements Runnable {
    private Poeple peo;
    private Integer count;
    private Semaphore s;
    private List<Poeple> peoList;

    public ThreadWrite(List<Poeple> peoList, Integer count, Semaphore s) {
        this.peoList = peoList;
        this.count = count;
        this.s = s;
    }

    @Override
    public void run() {
        /*訊號量*/
        try {
            s.acquire();//獲取鎖
            System.out.println("ThreadWrite");
            Poeple poeple = new Poeple();
            poeple.setName("name1");
            poeple.setSex("nv");
            peoList.add(poeple);
            System.out.println(Thread.currentThread().getName() + "=========>" + peoList.size());
            s.release();//釋放鎖
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public static void main(String[] args) {
    Semaphore s = new Semaphore(3);//訊號量 同時處理三個執行緒
    List<Poeple> peo = new ArrayList<>();
    int count = 0;
    for (int i = 0; i < 20; i++) {
        new Thread(new ThreadWrite(peo,count,s),"執行緒1").start();
        new Thread(new ThreadWrite(peo,count,s),"執行緒2").start();
        new Thread(new ThreadWrite(peo,count,s),"執行緒3").start();
    }
}