文章出處

一、初識Concurrent

第一次看見concurrent的使用是在同事寫的一個抽取系統代碼里,當時這部分代碼沒有完成,有許多的問題,另一個同事接手了這部分代碼的功能開發,由于他沒有多線程開發的經驗,所以我就一起幫著分析。最開始看到這個時很煩燥啊,因為自己接觸java時間很短,連synchronized都不知道怎么用呢,突然發現有這么個復雜的東西。當時就只好開始學習吧,畢竟是使用嘛,第一目的就是了解清楚這玩意的各個類與方法都干嘛用的,然后看了看同事的代碼大概也就清楚了。感覺這和大部分人一樣,能用就行。

下面是一段其中的應用

public class VoiceExtractRunnable implements Runnable {
 
    @Override
    public void run() {

        // 創建線程池
        ExecutorService service = Executors.newCachedThreadPool();
        // 聲明保存各任務(線程)執行結果的集合
        List<Future<VoiceExtractExpertInRuleVO>> futures = new ArrayList<Future<VoiceExtractExpertInRuleVO>>(
                rules.size());
        // 循環提交任務
        for (VoiceExtractExpertInRuleVO ruleVO : rules) {
            ruleVO.setExtractParamVO(vo);
            futures.add(service.submit(new VoiceRuleCallable(ruleVO)));
        }

        for (Future<VoiceExtractExpertInRuleVO> f : futures) {
            try {
                VoiceExtractExpertInRuleVO r = f.get();
                returnRules.add(r); // 獲取任務執行完成后的返回結果
            } catch (Exception e) {
                logger.error("", e);
            }
        }
        // 所有任務都執行完畢后,關閉線程池
        service.shutdown();
    }

}

看完這個代碼(省略了大部分的業務邏輯代碼)就能感覺到一個優點,就是線程的執行和結果獲取是可以異步的,這樣對于開發來說確實是有很大的幫助。代碼結構也比較清晰。

但這個時候我主要還是在能用就行的階段,而且也并不關心concurrent里到底有多少重要的代碼。最近在學習JAVA的基礎知識,看到線程安全的時候Concurrent開始進入我的視野,這時我才知道它原來是這么豐富,所以才開始一點點的了解。這個過程中也一直感覺到寫這些代碼的工程師確實厲害,能在實踐的過程中總結出這么好的代碼,供廣大的開發們使用。

二、主要的類

Executor :具體Runnable任務的執行者。
ExecutorService :一個線程池管理者,其實現類有多種,我會介紹一部分。我們能把Runnable,Callable提交到池中讓其調度。
Semaphore :一個計數信號量
ReentrantLock :一個可重入的互斥鎖定 Lock,功能類似synchronized,但要強大的多。
Future :是與Runnable,Callable進行交互的接口,比如一個線程執行結束后取返回的結果等等,還提供了cancel終止線程。
BlockingQueue :阻塞隊列。
CompletionService : ExecutorService的擴展,可以獲得線程執行結果的
CountDownLatch :一個同步輔助類,在完成一組正在其他線程中執行的操作之前,它允許一個或多個線程一直等待。 
CyclicBarrier :一個同步輔助類,它允許一組線程互相等待,直到到達某個公共屏障點 
Future :Future 表示異步計算的結果。
ScheduledExecutorService :一個 ExecutorService,可安排在給定的延遲后運行或定期執行的命令。

上面是一些常用類,參考這個文章,寫的比較清楚:http://www.cnblogs.com/aurawing/articles/1887056.html

我個人看了代碼后對下面的這些類印象比較深刻:

ConcurrentHashMap:支持并發的hashMap

AbstractQueuedSynchronizer:提供了同步鎖的基礎功能實現,包含獨占鎖和共享鎖

 對于ConcurrentHashMap這個類是一種適應于并發場景下的hashMap,是建立在分離鎖基礎上。其內部結構可以劃分為N個段,每個段都有自己的并發鎖,這樣寫入時可以寫入不同的段中,從而提高了并發的性能。

參考:http://blog.csdn.net/fw0124/article/details/43308193

AbstractQueuedSynchronizer是Concurrent包中對鎖的關鍵抽象實現,主要是提供了一個state字段用于控制并發,通過控制state的原子狀態從而保證多線程時的鎖機制。這個類是抽象類,很多的場景實現需要在特定的子類中實現。

參考:

http://www.infoq.com/cn/articles/jdk1.8-abstractqueuedsynchronizer

http://www.infoq.com/cn/articles/java8-abstractqueuedsynchronizer

三、學習到的一些知識點

這幾天在看源代碼中也不斷的在網上查找各種資料,還是學到了不少東西。

 分拆鎖(lock spliting)就是若原先的程序中多處邏輯都采用同一個鎖,但各個邏輯之間又相互獨立,就可以拆(Spliting)為使用多個鎖,每個鎖守護不同的邏輯。

分拆鎖有時候可以被擴展,分成可大可小加鎖塊的集合,并且它們歸屬于相互獨立的對象,這樣的情況就是分離鎖(lock striping)。(摘自《Java并發編程實踐》)

 

對于分離鎖有個更好些的解釋:分拆鎖有時候可以被擴展,分成若干加鎖塊的集合,并且它們歸屬于相互獨立的對象,這樣的情況就是分離鎖。例如,ConcurrentHashMap 的實現使用了一個包含 16 個鎖的數組,每一個鎖都守護 HashMap 的 1/16 。假設 Hash 值均勻分布,這將會把對于鎖的請求減少到約為原來的 1/16 。這項技術使得 ConcurrentHashMap 能夠支持 16 個的并發 Writer 。當多處理器系統的大負荷訪問需要更好的并發性時,鎖的數量還可以增加。——摘自developerworks

 

sun.misc.Unsafe 是一個封裝了很多底層操作的類,但是網上沒找到太多的資料,但在Concurrent包中用的比較多,最為關鍵的是其提供的方法compareAndSwap之類的方法是原子的,可以不用自己加鎖。看了Concurrent包中的鎖主要是通過這個方法來實現的鎖狀態管理。

但網上也提到他可以操作內存,也難怪叫Unsafe這名,如果在java代碼里隨便用的話那Java不就變成和C++差不多了,呵呵。所以除了在JDK里的單元,自己寫的代碼中不能直接使用這個類。

 

volatile關鍵字:這個關鍵字是要求多線程環境下訪問受volatile修改的共享數據時具有可見性。

 

我確實不知道怎么解釋它,推薦兩篇不錯的文章:

http://www.ibm.com/developerworks/cn/java/j-jtp06197.html

http://www.cnblogs.com/dolphin0520/p/3920373.html

 四、小感慨

在看著Concurrent包里的代碼時,確實對一些精秒的設計很感嘆,比如鎖的設計,一種抽象與實現結合的良好設計。里面的許多小細節都體現了技術的功底,反想自己為什么設計不出這樣的代碼。

我感覺兩方面:

1、沒有實際的問題要去解決

比如Concurrent這里面的代碼針對并發的編程,說實話工作中遇到的不多,一般的情況用用synchronized也是可以解決的,以前在.net里也就用用lock關鍵字。delphi用的時候也簡單。所以沒有一個好的工作場景讓你去解決這些問題,說實話想都想不到。

2、基礎不扎實

其實看了許多代碼都是些基礎應用,你說流、文件、并發這些東西都是計算機里都要面對的問題,只要掌握了這些知識,其實在實際遇到問題的時候就可以用上了。否則就會當作難題用一些其他方法規避掉,反而失去了寫出更好代碼的機會,時間長了就變的平庸

 

以后還是要多多努力學習基礎,這一段時間以來我覺得自己可以在編程上有更多的收獲,或許我真的能寫代碼到50歲,至少我覺得50歲的時候還是可以跟上時代,寫出優秀的代碼。


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 AutoPoster 的頭像
    AutoPoster

    互聯網 - 大數據

    AutoPoster 發表在 痞客邦 留言(0) 人氣()