高級多線程控制類

原文鏈接:https://blog.csdn.net/xh921/article/details/76871093

1.ThreadLocal類

用處:保存線程的獨立變量。當一個線程類在使用ThreadLocal維護變量時,ThreadLocal爲每個使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。常用於用戶登錄控制,如記錄session信息。

實現:每個Thread都持有一個TreadLocalMap類型的變量(該類是一個輕量級的Map,功能與map一樣,區別是桶裏放的是entry而不是entry的鏈表。功能還是一個map。)以本身爲key,以目標爲value。
主要方法是get()和set(), ThreadLocal是一個特殊的容器。

        2.原子類(AtomicInteger、AtomicBoolean……)

如果使用atomicInteger,或者使用自己保證原子的操作,則等同於synchronized

//返回值爲boolean

AtomicInteger.compareAndSet(intexpect,int update)

該方法可用於實現樂觀鎖。

       3.Lock類 

lock: 在java.util.concurrent包內。共有三個實現:

ReentrantLock

ReentrantReadWriteLock.ReadLock

ReentrantReadWriteLock.WriteLock

主要目的是和synchronized一樣, 兩者都是爲了解決同步問題,處理資源爭端而產生的技術。功能類似但有一些區別。

區別如下:

lock更靈活,可以自由定義多把鎖的枷鎖解鎖順序(synchronized要按照先加的後解順序)

提供多種加鎖方案,lock 阻塞式, trylock 無阻塞式, lockInterruptily 可打斷式,還有trylock的帶超時時間版本。

ReentrantLock    
可重入的意義在於持有鎖的線程可以繼續持有,並且要釋放對等的次數後才真正釋放該鎖。
         使用方法是:

1.先new一個實例

static ReentrantLock r=newReentrantLock();

2.加鎖      

r.lock()或r.lockInterruptibly();

此處也是個不同,後者可被打斷。當a線程lock後,b線程阻塞,此時如果是lockInterruptibly,那麼在調用b.interrupt()之後,b線程退出阻塞,並放棄對資源的爭搶,進入catch塊。(如果使用後者,必須throw interruptableexception 或catch)    

3.釋放鎖   

r.unlock()

必須做!何爲必須做呢,要放在finally裏面。以防止異常跳出了正常流程,導致災難。這裏補充一個小知識點,finally是可以信任的:經過測試,哪怕是發生了OutofMemoryError,finally塊中的語句執行也能夠得到保證。

ReentrantReadWriteLock

可重入讀寫鎖(讀寫鎖的一個實現) 

 ReentrantReadWriteLock lock = newReentrantReadWriteLock()

  ReadLock r = lock.readLock();

  WriteLock w = lock.writeLock();

兩者都有lock,unlock方法。寫寫,寫讀互斥;讀讀不互斥。可以實現併發讀的高效線程安全代碼

4.容器類

BlockingQueue

ConcurrentHashMap

BlockingQueue
阻塞隊列。該類是java.util.concurrent包下的重要類,通過對Queue的學習可以得知,這個queue是單向隊列,可以在隊列頭添加元素和在隊尾刪除或取出元素。類似於一個管  道,特別適用於先進先出策略的一些應用場景。普通的queue接口主要實現有PriorityQueue(優先隊列),有興趣可以研究

BlockingQueue在隊列的基礎上添加了多線程協作的功能:

BlockingQueue
除了傳統的queue功能(表格左邊的兩列)之外,還提供了阻塞接口put和take,帶超時功能的阻塞接口offer和poll。put會在隊列滿的時候阻塞,直到有空間時被喚醒;take在隊 列空的時候阻塞,直到有東西拿的時候才被喚醒。用於生產者-消費者模型尤其好用,堪稱神器。

常見的阻塞隊列有:

ArrayListBlockingQueue

LinkedListBlockingQueue

DelayQueue

SynchronousQueue

ConcurrentHashMap
高效的線程安全哈希map。請對比hashTable ,concurrentHashMap, HashMap

5.管理類

管理類的概念比較泛,用於管理線程,本身不是多線程的,但提供了一些機制來利用上述的工具做一些封裝。
瞭解到的值得一提的管理類:ThreadPoolExecutor和 JMX框架下的系統級管理類 ThreadMXBean
ThreadPoolExecutor
如果不瞭解這個類,應該瞭解前面提到的ExecutorService,開一個自己的線程池非常方便:


ExecutorService e =Executors.newCachedThreadPool();

   ExecutorService e = Executors.newSingleThreadExecutor();

   ExecutorService e = Executors.newFixedThreadPool(3);

    //第一種是可變大小線程池,按照任務數來分配線程,

    //第二種是單線程池,相當於FixedThreadPool(1)

    //第三種是固定大小線程池。

    //然後運行

   e.execute(new MyRunnableImpl());

該類內部是通過ThreadPoolExecutor實現的,掌握該類有助於理解線程池的管理,本質上,他們都是ThreadPoolExecutor類的各種實現版本

corePoolSize:池內線程初始值與最小值,就算是空閒狀態,也會保持該數量線程。

maximumPoolSize:線程最大值,線程的增長始終不會超過該值。

keepAliveTime:當池內線程數高於corePoolSize時,經過多少時間多餘的空閒線程纔會被回收。回收前處於wait狀態

unit:

時間單位,可以使用TimeUnit的實例,如TimeUnit.MILLISECONDS 

workQueue:待入任務(Runnable)的等待場所,該參數主要影響調度策略,如公平與否,是否產生餓死(starving)

threadFactory:線程工廠類,有默認實現,如果有自定義的需要則需要自己實現ThreadFactory接口並作爲參數傳入。

 

 

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