JDK併發包

整理來源:http://www.javashuo.com/article/p-xkdlaiet-cc.htmlhtml

ReentrantLock

        可重入: 單線程能夠重複進入,但要重複退出
        可中斷: lock.lockInterruptibly()
        可限時: 超時不能得到鎖,就返回false,不會永久等待構成死鎖
        公平鎖: 先來先得, public ReentrantLock(boolean fair), 默認鎖不公平的, 根據線程優先級競爭
        reentrantlock須要手工釋放鎖經過調用(unlock()方法),默認爲非公平鎖,new ReentrantLock(true)設置爲公平鎖能夠防止飢餓現象
      數組

public interface Lock {

     // 獲取鎖,若當前lock被其餘線程獲取;則此線程阻塞等待lock被釋放
     // 若是採用Lock,必須主動去釋放鎖,而且在發生異常時,不會自動釋放鎖
    void lock();

    // 獲取鎖,若當前鎖不可用(被其餘線程獲取);
    // 則阻塞線程,等待獲取鎖,則這個線程可以響應中斷,即中斷線程的等待狀態
    void lockInterruptibly() throws InterruptedException;

    // 來嘗試獲取鎖,若是獲取成功,則返回true;
    // 若是獲取失敗(即鎖已被其餘線程獲取),則返回false
    // 也就是說,這個方法不管如何都會當即返回
    boolean tryLock();

    // 在拿不到鎖時會等待必定的時間
    // 等待過程當中,能夠被中斷
    // 超過期間,依然獲取不到,則返回false;不然返回true
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

    // 釋放鎖
    void unlock();

    // 返回一個綁定該lock的Condtion對象
    // 在Condition#await()以前,鎖會被該線程持有
    // Condition#await() 會自動釋放鎖,在wait返回以後,會自動獲取鎖
    Condition newCondition();
}

condition:      多線程

public interface Condition {
    void await() throws InterruptedException;
    void awaitUninterruptibly();
    long awaitNanos(long nanosTimeout) throws InterruptedException;
    boolean await(long time, TimeUnit unit) throws InterruptedException;
    boolean awaitUntil(Date deadline) throws InterruptedException;
    void signal();
    void signalAll();
}

說明
await()方法會使當前線程等待,同時釋放當前鎖,當其餘線程中使用signal()時或者signalAll()方法時,線程會從新得到鎖並繼續執行。或者當線程被中斷時,也能跳出等待。這和Object.wait()方法很類似。
awaitUninterruptibly()方法與await()方法基本相同,但awaitUninterruptibly()方法不會在等待過程當中響應中斷。
singal()方法用於喚醒一個在等待中的線程。相對的singalAll()方法會喚醒全部在等待中的線程。這和Obejct.notify()方法相似。
condition.await()方法必須在lock.lock()與lock.unlock()方法之間調用併發

Semaphore信號量
    做用:
控制線程的併發數量
    Semaphore主要方法:
          acquire( int permits ) 參數做用,及動態添加 permits 許可數量
          availablePermits() 返回 Semaphore 對象中的當前可用許可數
         drainPermits() 方法可獲取並返回當即可用的全部許可(通路)個數,並將可用許可置爲0。
         getQueueLength() 獲取等待許可的線程個數。
    hasQueuedThreads() 判斷有沒有線程在等待這個許可。
         Semaphore semaphore = new Semaphore(int permits , boolean isFair) isFair 爲 true,則表示公平,先啓動的線程先獲鎖
         tryAcquire() 、 tryAcquire(int permits)、 tryAcquire(int permits , long timeout , TimeUint unit)獲取許可通道數timeout時間內
ReadWriteLock:
讀寫分離鎖, 能夠大幅提高系統並行度.
    讀-讀不互斥:讀讀之間不阻塞。
    讀-寫互斥:讀阻塞寫,寫也會阻塞讀。
    寫-寫互斥:寫寫阻塞。
CountDownLatch:倒數計時器

CountDownLatch(int count) //實例化一個倒計數器,count指定計數個數
countDown() // 計數減一
await() //等待,當計數減到0時,全部線程並行執行

public class CountDownLatchDemo implements Runnable{

    static final CountDownLatch latch = new CountDownLatch(10);
    static final CountDownLatchDemo demo = new CountDownLatchDemo();

    @Override
    public void run() {
        // 模擬檢查任務
        try {
            Thread.sleep(new Random().nextInt(10) * 1000);
            System.out.println("check complete");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //計數減一
            //放在finally避免任務執行過程出現異常,致使countDown()不能被執行
            latch.countDown();
        }
    }


    public static void main(String[] args) throws InterruptedException {
        ExecutorService exec = Executors.newFixedThreadPool(10);
        for (int i=0; i<10; i++){
            exec.submit(demo);
        }

        // 等待檢查
        latch.await();

        // 發射火箭
        System.out.println("Fire!");
        // 關閉線程池
        exec.shutdown();
    }
}

CyclicBarrier:循環柵欄
1.CyclicBarrier(int parties, Runnable barrierAction) 建立一個CyclicBarrier實例,parties指定參與相互等待的線程數,barrierAction指定當全部線程到達屏障點以後,首先執行的操做,該操做由最後一個進入屏障點的線程執行。
2.CyclicBarrier(int parties) 建立一個CyclicBarrier實例,parties指定參與相互等待的線程數。
3.getParties() 返回參與相互等待的線程數。
4.await() 該方法被調用時表示當前線程已經到達屏障點,當前線程阻塞進入休眠狀態,直到全部線程都到達屏障點,當前線程纔會被喚醒。
5.await(long timeout, TimeUnit unit) 該方法被調用時表示當前線程已經到達屏障點,當前線程阻塞進入休眠狀態,在timeout指定的超時時間內,等待其餘參與線程到達屏障點;若是超出指定的等待時間,則拋出TimeoutException異常,若是該時間小於等於零,則此方法根本不會等待。
6.isBroken() 判斷此屏障是否處於中斷狀態。若是由於構造或最後一次重置而致使中斷或超時,從而使一個或多個參與者擺脫此屏障點,或者由於異常而致使某個屏障操做失敗,則返回true;不然返回false。
7.reset() 將屏障重置爲其初始狀態。
8.getNumberWaiting() 返回當前在屏障處等待的參與者數目,此方法主要用於調試和斷言。

static class TaskThread extends Thread {
        
        CyclicBarrier barrier;
        
        public TaskThread(CyclicBarrier barrier) {
            this.barrier = barrier;
        }
        
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
                System.out.println(getName() + " 到達柵欄 A");
                barrier.await();
                System.out.println(getName() + " 衝破柵欄 A");
                
                Thread.sleep(2000);
                System.out.println(getName() + " 到達柵欄 B");
                barrier.await();
                System.out.println(getName() + " 衝破柵欄 B");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args) {
        int threadNum =5;
        CyclicBarrier barrier = new CyclicBarrier(threadNum, new Runnable() {
            
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " 完成最後任務");
            }
        });
        
        for(int i = 0; i < threadNum; i++) {
            new TaskThread(barrier).start();
        }
    }
}

LockSupport:一個線程阻塞工具, 能夠在任意位置讓線程阻塞.
 dom

LockSupport.park();
LockSupport.unpark(t1);

優勢:LockSupport不須要在同步代碼塊裏 。因此線程間也不須要維護一個共享的同步對象了,實現了線程間的解耦
          unpark函數能夠先於park調用,因此不須要擔憂線程間的執行的前後順序ide

併發容器函數

synchronizedMap
ConcurrentHashMap
BlockingQueue:阻塞隊列, 主要用於多線程之間共享數據.當一個線程讀取數據時, 若是隊列是空的, 則當前線程會進入等待狀態.若是隊列滿了, 當一個線程嘗試寫入數據時, 一樣會進入等待狀態.
CopyOnWriteArrayList:經過在新增元素時, 複製一份新的數組出來, 並在其中寫入數據, 以後將原數組引用指向到新數組.其Add操做是在內部經過ReentrantLock進行鎖保護, 防止多線程場景複製多份數組.而Read操做內部無鎖, 直接返回數組引用, 併發下效率高, 所以適用於讀多寫少的場景工具

相關文章
相關標籤/搜索