java併發包小結(二)

接上一篇    

java併發包小結(一)http://blog.csdn.net/aalansehaiyang52/article/details/8877579


Future 接口
Future 接口允許表示已經完成的任務、正在執行過程中的任務或者尚未開始執行的任務。通過 Future 接口,可以嘗試取消尚未完成的任務,查詢任務已經完成還是取消了,以及提取(或等待)任務的結果值。
FutureTask 類實現了 Future,幷包含一些構造函數,允許將 Runnable 或 Callable(會產生結果的 Runnable)和 Future 接口封裝。因爲 FutureTask 也實現 Runnable,所以可以只將 FutureTask 提供給 Executor。一些提交方法(如 ExecutorService.submit())除了提交任務之外,還將返回 Future 接口。
Future.get() 方法獲取任務計算的結果(或如果任務完成,但有異常,則拋出 ExecutionException)。如果任務尚未完成,那麼 Future.get() 將被阻塞,直到任務完成;如果任務已經完成,那麼它將立即返回結果。


使用 Future 構建緩存
該示例代碼與 java.util.concurrent 中的多個類關聯,突出顯示了 Future 的功能。它實現緩存,使用 Future 描述緩存值,該值可能已經計算,或者可能在其他線程中'正在構造'。
它利用 ConcurrentHashMap 中的原子 putIfAbsent() 方法,確保僅有一個線程試圖計算給定關鍵字的值。如果其他線程隨後請求同一關鍵字的值,它僅能等待(通過 Future.get() 的幫助)第一個線程完成。因此兩個線程不會計算相同的值。

public class Cache {

    ConcurrentMap  map = new ConcurrentHashMap();

    Executor executor = Executors.newFixedThreadPool(8);

    public V get(final K key) {

        FutureTask f = map.get(key);

        if (f == null) {

            Callable c = new Callable() {

                public V call() {

                    // return value associated with key

                }

            };

            f = new FutureTask(c);

            FutureTask old = map.putIfAbsent(key, f);

            if (old == null)

                executor.execute(f);

            else

                f = old;

        }

        return f.get();

    }

}

Semaphore
Semaphore 類實現標準 Dijkstra 計數信號。計數信號可以認爲具有一定數量的許可權,該許可權可以獲得或釋放。如果有剩餘的許可權,acquire() 方法將成功,否則該方法將被阻塞,直到有可用的許可權(通過其他線程釋放許可權)。線程一次可以獲得多個許可權。
注意信號不跟蹤哪個線程擁有多少許可權;這由應用程序來決定,以確保何時線程釋放許可權,該信號表示其他線程擁有許可權或者正在釋放許可權,以及其他線程知道它的許可權已釋放。


CountdownLatch
CountdownLatch 類與 CyclicBarrier 相似,因爲它的角色是對已經在它們中間分攤了問題的一組線程進行協調。它也是使用整型變量構造的,指明計數的初始值,但是與 CyclicBarrier 不同的是,CountdownLatch 不能重新使用。
其中,CyclicBarrier 是到達屏障的所有線程的大門,只有當所有線程都已經到達屏障或屏障被打破時,才允許這些線程通過,CountdownLatch 將到達和等待功能分離。任何線程都可以通過調用 countDown() 減少當前計數,這種不會阻塞線程,而只是減少計數。await() 方法的行爲與 CyclicBarrier.await() 稍微有所不同,調用 await() 任何線程都會被阻塞,直到閂鎖計數減少爲零,在該點等待的所有線程才被釋放,對 await() 的後續調用將立即返回。
當問題已經分解爲許多部分,每個線程都被分配一部分計算時,CountdownLatch非常有用。在工作線程結束時,它們將減少計數,協調線程可以在閂鎖處等待當前這一批計算結束,然後繼續移至下一批計算。
相反地,具有計數 1 的 CountdownLatch 類可以用作'啓動大門',來立即啓動一組線程;工作線程可以在閂鎖處等待,協調線程減少計數,從而立即釋放所有工作線程。下例使用兩個 CountdownLatche。一個作爲啓動大門,一個在所有工作線程結束時釋放線程:

class Driver { // ...

   void main() throws InterruptedException {

     CountDownLatch startSignal = new CountDownLatch(1);

     CountDownLatch doneSignal = new CountDownLatch(N);

     for (int i = 0; i < N; ++i) // create and start threads

       new Thread(new Worker(startSignal, doneSignal)).start();

     doSomethingElse();            // don't let them run yet

     startSignal.countDown();      // let all threads proceed

     doSomethingElse();

     doneSignal.await();           // wait for all to finish

   }

 }

 class Worker implements Runnable {

   private final CountDownLatch startSignal;

   private final CountDownLatch doneSignal;

   Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {

      this.startSignal = startSignal;

      this.doneSignal = doneSignal;

   }

   public void run() {

      try {

        startSignal.await();

        doWork();

        doneSignal.countDown();

      } catch (InterruptedException ex) {} // return;

   }

 }

Hashtable 與 ConcurrentHashMap
作爲可伸縮性的例子,ConcurrentHashMap 實現設計的可伸縮性要比其線程安全的上一代 Hashtable 的可伸縮性強得多。Hashtable 一次只允許一個線程訪問 Map;ConcurrentHashMap 允許多個讀者併發執行,讀者與寫入者併發執行,以及一些寫入者併發執行。因此,如果許多線程頻繁訪問共享映射,使用 ConcurrentHashMap 的總的吞吐量要比使用 Hashtable 的好。
下表大致說明了 Hashtable 和 ConcurrentHashMap 之間的可伸縮性差別。在每次運行時,N 個線程併發執行緊密循環,它們從 Hashtable 或 ConcurrentHashMap 中檢索隨即關鍵字,60% 的失敗檢索將執行 put() 操作,2% 的成功檢索執行 remove() 操作。測試在運行 Linux 的雙處理器 Xeon 系統中執行。數據顯示 10,000,000 個迭代的運行時間,對於 ConcurrentHashMap,標準化爲一個線程的情況。可以看到直到許多線程,ConcurrentHashMap 的性能仍保持可伸縮性,而 Hashtable 的性能在出現鎖定競爭時幾乎立即下降。
與通常的服務器應用程序相比,這個測試中的線程數看起來很少。然而,因爲每個線程未進行其他操作,僅是重複地選擇使用該表,所以這樣可以模擬在執行一些實際工作的情況下使用該表的大量線程的競爭。

線程 ConcurrentHashMap Hashtable
1 1.0 1.51
2 1.44 17.09
4 1.83 29.9
8 4.06 54.06
16 7.5 119.44
32 15.32 237.2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章