1. 程式人生 > >Java高併發程式設計

Java高併發程式設計

第一章  走入並行世界

關於並行的兩個定律: Amdahl定律 和Gustafson定律 考慮方向不同

Java記憶體模型 JMM 原子性 可見性 有序性

第二章 Java並行程式基礎

    執行緒建立: new Thread(Runable).start()

    執行緒終止: stop 方法  會立即釋放鎖,導致資料不一致問題,已經廢棄

    執行緒中斷: interrupt() 設定中斷標識,run方法中可以依靠這個做執行緒退出的邏輯處理Thread.interrupted()用來判斷

    等待和通知:wait()和notify()必須在synchronized中,涉及到鎖的操作

    掛起和繼續執行:suspend 和 resume 已經廢棄

    等待執行緒結束和謙讓:

              如果一個執行緒A依賴另外一個執行緒B,那就在A中執行B.join() 即 A要等待執行緒B結束

              yield()是讓出CPU資源,但是還是會進行資源競爭.

    volatile關鍵字:保證執行緒間的可見性和禁止執行重排(有序性)但是不能保證原子性  JMM

    守護執行緒: daemon 後臺執行緒,當用戶執行緒都結束時,守護執行緒也會結束,如垃圾回收執行緒

第三章 JDK併發包

    1.同步控制 

       1.1可重入鎖 ReentrantLock

            ReentrantLock  lock  = new ReentrantLock()

            lock.lock() 加鎖

            lock.unlock解鎖

            對同一個執行緒而言,可以重複的加鎖,也要解相同次數的鎖才行

            中斷響應: lock.lockInterruptibly() 會對thread.interrupt()丟擲異常,對其進行處理即可

            限時申請鎖: lock.tryLock(time,timeUnit.xxx) 在限定時間內申請獲取鎖,成功返回true 失敗返回false

            公平鎖:  ReentrantLock  lock  = new ReentrantLock(true) 預設非公平,公平鎖需要維護一個執行緒申請鎖的佇列

       1.2 重入鎖好搭檔: Conditon 條件

             Condition condition  =  lock.newCondition()

             condition的用法類似於object.wait() 和 object.notify()

             await()方法會使當前執行緒等待,同時釋放當前鎖,當其他執行緒中使用signal()或者signalAll()方法是,執行緒活重新獲取鎖,繼續執行.

             當前執行緒被中斷時也能跳出等待.

             awaitUninterruptibly() 和 await()類似,但是不會中斷相應

             singal()喚醒一個執行緒,singalAll()喚醒所有執行緒.

             併發容器中使用兩個condition實現佇列的take和put的阻塞.見ArrayBlockingQueue原始碼

        1.3 允許多執行緒同時訪問: 訊號量 Semaphore 

              Semaphore (int permits) 或者 Semaphore (int permits,boolean fair)  數量 和 公平

              大家看方法就能猜如來如何使用了

              acquire() 獲取一個憑證

              acquireUninterruptibly() 獲取憑證對中斷響應

              tryAcquire() 不等待獲取憑證 類似 tryLock()

              tryAcquire(timeout,unit) 指定時間內獲取憑證

              release() 釋放憑證

        1.4 ReadWriteLock 讀寫鎖

              ReentrantReadWriteLock readWriteLock = new   ReentrantReadWriteLock ();

              Lock  readLock  = readWriteLock.readLock(); 讀鎖

              Lock  writeLock = readWriteLock.writeLock(); 寫鎖

              讀讀不互斥,寫寫互斥,讀寫互斥.

        1.5  CountDownLatch 倒計時器

               這個很常見不就寫了

        1.6  迴圈柵欄: CyclicBarrier

               和CountDownLatch類似但比其強大.

                CyclicBarrier(int parties,Runnable barrieraction)

                迴圈柵欄會阻塞 xxx.await()直到滿足數目才讓執行緒一起向下執行,且在此之前會執行一次 barrieraction中run方法 

        1.7  執行緒阻塞工具類: LockSupport

               它可以線上程內任意位置讓執行緒阻塞.

                LockSupport.park() 可以阻塞當前執行緒,類似的還有parkNanos(),parkUntil()等實現一個閒時的阻塞

                LockSupprot.unpark(Thread) 釋放指定執行緒的阻塞

 2. 執行緒複用:執行緒池

     這個就不浪費筆墨了,依託底層 ThreadPoolExecutor實現了幾種常用的執行緒池工具,大家應該都明白的.

     執行緒池可以根據自己的需求進行相應的自定義處理:

     ThreadPoolExecutor提供了beforeExecute() ,afterExecute(),terminated() 方法對其進行控制.

      執行緒數量選取: Nthreads = Nepu * Ucpu * ( 1 + W/C) 即 cpu數量 * 目標Cpu使用率 *(1 + 等待時間與計算時間比)

      分而治之:Fork/Join框架

      ForkJoinPool.submit(ForkJoinTask) 提交任務 task.fork() 執行結束後 使用 task.join收集結果

 3. JDK併發容器

     1. 併發集合

         ConcurrenHashMap

         CopyOnWriteArrayList

         ConcurrentLinkedQueue

         BlockingQueue 

         ConcurrentSkipListMap

    2. 高效讀寫佇列:深度剖析 ConcurentLinkedQueue

        主要通過CAS(比較交換)操作和對head及tail的演算法實現高效的讀寫

    3. 高效讀取: 不變模式下的CopyOnWriteArrayList

        任何讀取操作沒有鎖相關操作,但是寫入時候.會加鎖,複製原來的集合寫一個新集合後替換老集合.

    4. 資料共享通道: BlockingQueue

        前面說過其take和put的通過兩個condition裡相互通知實現阻塞.

    5.隨機資料結構:跳錶(SkipList)

       維護多層連結串列,連結串列分層,通過空間換時間的方法來實現高速的查詢.