網(wǎng)頁網(wǎng)站制作維護十大經(jīng)典事件營銷案例分析
?
Callable接口
Callable是一個interface,相當(dāng)于給線程封裝了一個返回值,方便程序猿借助多線程的方式計算結(jié)果.
創(chuàng)建一個匿名內(nèi)部類, 實現(xiàn) Callable 接口. Callable 帶有泛型參數(shù). 泛型參數(shù)表示返回值的類型.
重寫 Callable 的 call 方法, 完成累加的過程. 直接通過返回值返回計算結(jié)果.
把 callable 實例使用 FutureTask 包裝一下.
創(chuàng)建線程, 線程的構(gòu)造方法傳入 FutureTask . 此時新線程就會執(zhí)行 FutureTask 內(nèi)部的 Callable 的 call 方法, 完成計算. 計算結(jié)果就放到了 FutureTask 對象中.
代碼示例: 使用 Callable 版本,創(chuàng)建線程計算 1 + 2 + 3 + … + 1000,
??????
在上面代碼中,get()方法會拋出異常.
理解Callable
- Callable 和 Runnable 相對, 都是描述一個 “任務(wù)”. Callable 描述的是帶有返回值的任務(wù), Runnable描述的是不帶返回值的任務(wù).
- Callable 通常需要搭配 FutureTask 來使用. FutureTask 用來保存Callable 的返回結(jié)果. 因為Callable 往往是在另一個線程中執(zhí)行的, 啥時候執(zhí)行完并不確定.
- FutureTask就可以負責(zé)這個等待結(jié)果出來的工作.
ReentrantLock類
可重入互斥鎖. 和 synchronized 定位類似, 都是用來實現(xiàn)互斥效果, 保證線程安全.
ReentrantLock的用法
????
ReentrantLock和Synchronized的區(qū)別
Synchronized是非公平鎖,ReentrantLock默認是非公平鎖,但可以通過一個構(gòu)造方法傳入true開啟公平鎖模式
Synchronized不需要手動釋放鎖,而ReentrantLock需要手動釋放鎖.
Synchronized提供的加鎖操作就是 死等.只要獲取不到鎖,就會一直阻塞等待.而ReentrantLock提供了更靈活的等待方式.
ReentrantLock提供了更強大,更方便的的等待通知機制.
Synchronized搭配的是wait notify,notify的時候是隨機喚醒一個等待線程,而ReentrantLock搭配的是Condition類,進行喚醒的時候可以喚醒指定線程.ReentrantLock t通常搭配 try catch 使用.
信號量 Semaphore
信號量, 用來表示 “可用資源的個數(shù)”. 本質(zhì)上就是一個計數(shù)器.
理解信號量
可以把信號量想象成是停車場的展示牌: 當(dāng)前有車位 100 個. 表示有 100 個可用資源.
P操作: 當(dāng)有車開進去的時候, 就相當(dāng)于申請一個可用資源, 可用車位就 -1 (這個稱為信號量的 P 操作)
V操作: 作當(dāng)有車開出來的時候, 就相當(dāng)于釋放一個可用資源, 可用車位就 +1 (這個稱為信號量的 V 操作)
釋放資源: 如果計數(shù)器的值已經(jīng)為 0 了, 還嘗試申請資源, 就會阻塞等待, 直到有其他線程釋放資源.
Semaphore 的 PV 操作中的加減計數(shù)器操作都是原子的, 可以在多線程環(huán)境下直接使用.
CountDownLatch
CountDownLatch的主要任務(wù)是等待N個任務(wù)執(zhí)行結(jié)束
- 構(gòu)造CountDownLatch實例,初始化10代表有10個任務(wù)要完成.
???????
- 每執(zhí)行完一個任務(wù),都會調(diào)用 count.countDown()方法,每調(diào)用一次, CountDownLatch內(nèi)部的計數(shù)器就會減1.
- 當(dāng)主線程中使用 latch.await(); 阻塞等待所有任務(wù)執(zhí)行完畢. 相當(dāng)于計數(shù)器為 0 了.
多線程使用哈希表
在之前數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)了哈希表,其中HashMap是線程不安全的,HashTable是線程安全的,
而這里主要講的是ConcurrentHashMap,是一種更優(yōu)化的線程安全哈希表.
???????
Synchronized加鎖是多個線程針對同一個對象加鎖,就會產(chǎn)生鎖競爭,一個HashTable只有一把鎖,此時兩個線程在訪問哈希表中的任意元素的時候都會發(fā)生鎖競爭.
ConcurrentHashMap任然是用synchronized進行加鎖,但不是整個鎖對象,而是鏈表的頭節(jié)點作為所對象,大大降低了鎖沖突的概率
ConcurrentHashMap針對讀操作不加鎖,但使用volatile保證從內(nèi)存讀取元素時原子的,而只針對寫操作進行加鎖.
ConcurrentHashMap內(nèi)部充分利用了CAS,進一步削減加鎖操作的數(shù)目.
針對擴容采取了化整為零的方式.
- HashTable/HashMap擴容:創(chuàng)建一個更大的數(shù)組,把舊的數(shù)組上的鏈表上的每個元素都搬入到新的數(shù)組,相當(dāng)于刪除原來數(shù)組在重新插入到新的數(shù)組上.這個擴容會在某次put時進行出發(fā),當(dāng)數(shù)據(jù)太多,就會導(dǎo)致這種擴容會比較耗時
- ConcurrentHashMap中,擴容的方式是每次搬運一小部分元素,創(chuàng)建新的數(shù)組,舊的數(shù)組保留,每次put操作,都忘新數(shù)組上添加,同時進行一部分搬運,每次get的時候,舊的數(shù)組和新的數(shù)組都查詢,每次remove只要找到元素刪除即可.經(jīng)過一定時間,所有的元素都搬運完了,最終在釋放舊數(shù)組.
?