經常使用Concurrent.util包工具類——高併發

一 Concurrent.util經常使用類:

1. CyclicBarrier: 假設有場景:每一個線程表明一個跑步運動員,當運動員都準備好後,才一塊兒出發只要有一我的沒有準備好,你們都等待。

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class UseCyclicBarrier {

    static class Runner implements Runnable {
        private CyclicBarrier barrier;
        private String name;
        
        public Runner(CyclicBarrier barrier, String name) {
            super();
            this.barrier = barrier;
            this.name = name;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(1000 * (new Random()).nextInt(5));
                System.out.println(name + "準備OK");
                barrier.await();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(name + "Go!");
        }
    }
    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(3);
        ExecutorService pool = Executors.newFixedThreadPool(3);
        pool.execute(new Runner(barrier, "b1"));
        pool.execute(new Runner(barrier, "b2"));
        pool.execute(new Runner(barrier, "b3"));
        pool.shutdown();
    }

}

運行結果:
b3準備OK
b2準備OK
b1準備OK
b2Go!
b1Go!
b3Go!java

2. CountDownLacth:常常用於監聽某些初始化操做,等初始化執行完畢後,通知主線程繼續工做

import java.util.concurrent.CountDownLatch;

public class UseCountDownLatch {

    public static void main(String[] args) {
        final CountDownLatch cDownLatch = new CountDownLatch(2);
        Thread t1 = new Thread(new Runnable() {
            
            @Override
            public void run() {
                System.out.println("進入線程t1,等待其餘線程處理完成...");
                try {
                    cDownLatch.await();
                    //當CountDownLatch構造函數的參數減爲0時,該線程才繼續執行
                    System.out.println("t1線程繼續執行...");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }, "t1");
        
        Thread t2 = new Thread(new Runnable() {
            
            @Override
            public void run() {
                System.out.println("t2線程執行初始化操做...");
                try {
                    Thread.sleep(3000);
                    System.out.println("t2線程初始化操做完成,通知t1線程繼續...");
                    cDownLatch.countDown();
                    //CountDownLatch構造函數的參數-1
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }, "t2");
        Thread t3 = new Thread(new Runnable() {
            
            @Override
            public void run() {
                System.out.println("t3線程執行初始化操做...");
                try {
                    Thread.sleep(4000);
                    System.out.println("t3線程初始化操做完成,通知t1線程繼續...");
                    cDownLatch.countDown();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }, "t3");
        t1.start();
        t2.start();
        t3.start();
    }

}

運行結果:
進入線程t1,等待其餘線程處理完成...
t2線程執行初始化操做...
t3線程執行初始化操做...
t2線程初始化操做完成,通知t1線程繼續...
t3線程初始化操做完成,通知t1線程繼續...
t1線程繼續執行...數據庫

區別:CyclicBarrier全部線程都阻塞;CountDownLatch只有一個(主)線程阻塞等待

3. Future和Callable:該模式很是適合在處理很耗時的業務邏輯時進行使用,能夠有效的減小系統的響應時間,提升系統的吞吐量

public class UseFuture implements Callable<String>{
    private String para;

    public UseFuture(String para) {
        super();
        this.para = para;
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        String querystr = "query";
        //構造FutureTask,而且傳入須要真正進行業務處理的類,該類實現了Callable接口
        FutureTask<String> future = new FutureTask<>(new UseFuture(querystr));
        FutureTask<String> future2 = new FutureTask<>(new UseFuture(querystr));
        //建立一個固定線程數量的線程池
        ExecutorService pool = Executors.newFixedThreadPool(2);
        //這裏提交任務的future,則開啓線程執行RealData的call()
        Future f = pool.submit(future);
        Future f2 = pool.submit(future2);
        //submit和execute的區別:submit能夠實現calabale接口的對象;submit有返回值
        System.out.println("請求完畢");
//      while(true) {
            //f.get()判斷RealData是否執行完畢
//          if(f.get() == null){
//              System.out.println("---------------");
                //future.get()獲取ReadData
//              System.out.println("數據:" + future.get());
//              break;
//          }
//      }
        try {
            //處理其餘實際業務邏輯
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("數據:" + future.get());
        System.out.println("數據:" + future2.get());
        //並行處理,一共等待3秒
        pool.shutdown();
    }

    @Override
    public String call() throws Exception {
        //模擬執行耗時
        Thread.sleep(3000);
        String result = this.para + "處理完成";
        return result;
    }

}

運行結果:
請求完畢
數據:query處理完成
數據:query處理完成服務器

4. Semaphore信號量

Semaphore信號量很是適合高併發訪問,新系統在上線以前,要對系統的訪問量進行評估,固然這個值確定不是隨便拍拍腦殼就能想出來的,是通過以往的經驗、數據、歷年的訪問量、以及推廣粒力度進行的一個合理的評估,固然評估標準不能太大也不能過小,太大的話投入的資源達不到實際效果,浪費資源,過小的話,某個時間點一個峯值的訪問量上來直接能夠壓垮系統。
相關概念:網絡

  1. PV(Page View):網站的總訪問量,頁面瀏覽量或點擊量,用戶每刷新一次就會被記錄一次
  2. UV(Unlque Visitor):訪問網站的一臺電腦客戶端爲一個訪客,通常來說,時間上以00:00-24:00以內相同IP的客戶端只記錄一次
  3. QPS(Query Per Second):每秒查詢數,qps很大程度上表明瞭系統業務的繁忙程度,每次請求的背後,可能對應着屢次磁盤IO,屢次網絡請求,多個cpu時間片等。咱們經過qps能夠很是直觀的瞭解當前系統業務狀況,一旦當前qps超過所設定的預警閥值,能夠考慮增長機器對集羣擴容,以避免壓力過大致使宕機,能夠根據前期的壓力測試獲得估值,再結合後期綜合運維狀況,結算出閥值。
  4. RT(Response Time):請求的響應時間,這個指標很是關鍵,直接說明前期用戶的體驗,所以任何系統設計師都想下降rt時間。
  5. 固然還涉及到cpu、內存、網絡、磁盤等狀況,更細節的問題不少,如select、update、delete/ps等數據庫層面的統計。

應對高併發環境:

  1. 網絡層面
  2. 服務層面:多臺ng服務器作分流負載均衡
  3. Java業務上進行模塊化劃分
相關文章
相關標籤/搜索