最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 高并發(fā)十: JDK8對并發(fā)的新支持詳解

 更新時間:2016年09月12日 09:20:08   作者:Hosee  
本文主要介紹Java 高并發(fā)JDK8的支持,這里整理了詳細(xì)的資料及1. LongAdder 2. CompletableFuture 3. StampedLock的介紹,有興趣的小伙伴可以參考下

1. LongAdder

和AtomicLong類似的使用方式,但是性能比AtomicLong更好。

LongAdder與AtomicLong都是使用了原子操作來提高性能。但是LongAdder在AtomicLong的基礎(chǔ)上進(jìn)行了熱點(diǎn)分離,熱點(diǎn)分離類似于有鎖操作中的減小鎖粒度,將一個鎖分離成若干個鎖來提高性能。在無鎖中,也可以用類似的方式來增加CAS的成功率,從而提高性能。

LongAdder原理圖:

AtomicLong的實(shí)現(xiàn)方式是內(nèi)部有個value 變量,當(dāng)多線程并發(fā)自增,自減時,均通過CAS 指令從機(jī)器指令級別操作保證并發(fā)的原子性。唯一會制約AtomicLong高效的原因是高并發(fā),高并發(fā)意味著CAS的失敗幾率更高, 重試次數(shù)更多,越多線程重試,CAS失敗幾率又越高,變成惡性循環(huán),AtomicLong效率降低。

而LongAdder將把一個value拆分成若干cell,把所有cell加起來,就是value。所以對LongAdder進(jìn)行加減操作,只需要對不同的cell來操作,不同的線程對不同的cell進(jìn)行CAS操作,CAS的成功率當(dāng)然高了(試想一下3+2+1=6,一個線程3+1,另一個線程2+1,最后是8,LongAdder沒有乘法除法的API)。

可是在并發(fā)數(shù)不是很高的情況,拆分成若干的cell,還需要維護(hù)cell和求和,效率不如AtomicLong的實(shí)現(xiàn)。LongAdder用了巧妙的辦法來解決了這個問題。

初始情況,LongAdder與AtomicLong是相同的,只有在CAS失敗時,才會將value拆分成cell,每失敗一次,都會增加cell的數(shù)量,這樣在低并發(fā)時,同樣高效,在高并發(fā)時,這種“自適應(yīng)”的處理方式,達(dá)到一定cell數(shù)量后,CAS將不會失敗,效率大大提高。

LongAdder是一種以空間換時間的策略。

2. CompletableFuture

實(shí)現(xiàn)CompletionStage接口(40余個方法),大多數(shù)方法多數(shù)應(yīng)用在函數(shù)式編程中。并且支持流式調(diào)用

CompletableFuture是Java 8中對Future的增強(qiáng)版

簡單實(shí)現(xiàn):

import java.util.concurrent.CompletableFuture;

public class AskThread implements Runnable {
 CompletableFuture<Integer> re = null;

 public AskThread(CompletableFuture<Integer> re) {
 this.re = re;
 }

 @Override
 public void run() {
 int myRe = 0;
 try {
 myRe = re.get() * re.get();
 } catch (Exception e) {
 }
 System.out.println(myRe);
 }

 public static void main(String[] args) throws InterruptedException {
 final CompletableFuture<Integer> future = new CompletableFuture<Integer>();
 new Thread(new AskThread(future)).start();
 // 模擬長時間的計算過程
 Thread.sleep(1000);
 // 告知完成結(jié)果
 future.complete(60);
 }
}

Future最令人詬病的就是要等待,要自己去檢查任務(wù)是否完成了,在Future中,任務(wù)完成的時間是不可控的。而 CompletableFuture的最大改進(jìn)在于,任務(wù)完成的時間也開放了出來。

future.complete(60);

用來設(shè)置完成時間。

CompletableFuture的異步執(zhí)行:

public static Integer calc(Integer para) {
 try {
 // 模擬一個長時間的執(zhí)行
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 }
 return para * para;
 }

 public static void main(String[] args) throws InterruptedException,
 ExecutionException {
 final CompletableFuture<Integer> future = CompletableFuture
 .supplyAsync(() -> calc(50));
 System.out.println(future.get());
 }
CompletableFuture的流式調(diào)用:

public static Integer calc(Integer para) {
 try {
 // 模擬一個長時間的執(zhí)行
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 }
 return para * para;
 }

 public static void main(String[] args) throws InterruptedException,
 ExecutionException {
 CompletableFuture<Void> fu = CompletableFuture
 .supplyAsync(() -> calc(50))
 .thenApply((i) -> Integer.toString(i))
 .thenApply((str) -> "\"" + str + "\"")
 .thenAccept(System.out::println);
 fu.get();
 }

組合多個CompletableFuture:

public static Integer calc(Integer para) {
 return para / 2;
 }

 public static void main(String[] args) throws InterruptedException,
 ExecutionException {
 CompletableFuture<Void> fu = CompletableFuture
 .supplyAsync(() -> calc(50))
 .thenCompose(
  (i) -> CompletableFuture.supplyAsync(() -> calc(i)))
 .thenApply((str) -> "\"" + str + "\"")
 .thenAccept(System.out::println);
 fu.get();
 }

這幾個例子更多是側(cè)重Java8的一些新特性,這里就簡單舉下例子來說明特性,就不深究了。
CompletableFuture跟性能上關(guān)系不大,更多的是為了支持函數(shù)式編程,在功能上的增強(qiáng)。當(dāng)然開放了完成時間的設(shè)置是一大亮點(diǎn)。

3. StampedLock

在上一篇中剛剛提到了鎖分離,而鎖分離的重要的實(shí)現(xiàn)就是ReadWriteLock。而StampedLock則是ReadWriteLock的一個改進(jìn)。StampedLock與ReadWriteLock的區(qū)別在于,StampedLock認(rèn)為讀不應(yīng)阻塞寫,StampedLock認(rèn)為當(dāng)讀寫互斥的時候,讀應(yīng)該是重讀,而不是不讓寫線程寫。這樣的設(shè)計解決了讀多寫少時,使用ReadWriteLock會產(chǎn)生寫線程饑餓現(xiàn)象。

所以StampedLock是一種偏向于寫線程的改進(jìn)。

StampedLock示例:

import java.util.concurrent.locks.StampedLock;

public class Point {
 private double x, y;
 private final StampedLock sl = new StampedLock();

 void move(double deltaX, double deltaY) { // an exclusively locked method
 long stamp = sl.writeLock();
 try {
 x += deltaX;
 y += deltaY;
 } finally {
 sl.unlockWrite(stamp);
 }
 }

 double distanceFromOrigin() { // A read-only method
 long stamp = sl.tryOptimisticRead();
 double currentX = x, currentY = y;
 if (!sl.validate(stamp)) {
 stamp = sl.readLock();
 try {
 currentX = x;
 currentY = y;
 } finally {
 sl.unlockRead(stamp);
 }
 }
 return Math.sqrt(currentX * currentX + currentY * currentY);
 }
}

上述代碼模擬了寫線程和讀線程, StampedLock根據(jù)stamp來查看是否互斥,寫一次stamp變增加某個值

tryOptimisticRead()

就是剛剛所說的讀寫不互斥的情況。

每次讀線程要讀時,會先判斷

if (!sl.validate(stamp))

validate中會先查看是否有寫線程在寫,然后再判斷輸入的值和當(dāng)前的 stamp是否相同,即判斷是否讀線程將讀到最新的數(shù)據(jù)。

如果有寫線程在寫,或者 stamp數(shù)值不同,則返回失敗。

如果判斷失敗,當(dāng)然可以重復(fù)的嘗試去讀,在示例代碼中,并沒有讓其重復(fù)嘗試讀,而采用的是將樂觀鎖退化成普通的讀鎖去讀,這種情況就是一種悲觀的讀法。

stamp = sl.readLock();

StampedLock的實(shí)現(xiàn)思想:

CLH自旋鎖:當(dāng)鎖申請失敗時,不會立即將讀線程掛起,在鎖當(dāng)中會維護(hù)一個等待線程隊(duì)列,所有申請鎖,但是沒有成功的線程都記錄在這個隊(duì)列中。每一個節(jié)點(diǎn)(一個節(jié)點(diǎn)代表一個線程),保存一個標(biāo)記位(locked),用于判斷當(dāng)前線程是否已經(jīng)釋放鎖。當(dāng)一個線程試圖獲得鎖時,取得當(dāng)前等待隊(duì)列的尾部節(jié)點(diǎn)作為其前序節(jié)點(diǎn)。并使用類似如下代碼判斷前序節(jié)點(diǎn)是否已經(jīng)成功釋放鎖

while (pred.locked) {  
}

這個循環(huán)就是不斷等前面那個結(jié)點(diǎn)釋放鎖,這樣的自旋使得當(dāng)前線程不會被操作系統(tǒng)掛起,從而提高了性能。
當(dāng)然不會進(jìn)行無休止的自旋,會在若干次自旋后掛起線程。

相關(guān)文章

  • java打jar包的幾種方式詳解

    java打jar包的幾種方式詳解

    這篇文章主要介紹了java打jar包的幾種方式,本文分步驟給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-11-11
  • JavaCV 圖像邊緣檢測之Canny 算法詳解

    JavaCV 圖像邊緣檢測之Canny 算法詳解

    在圖像處理中,邊緣檢測是基礎(chǔ)且關(guān)鍵的一環(huán),其中Canny邊緣檢測算法以其高精度和可靠性著稱,本文詳細(xì)介紹了使用JavaCV庫實(shí)現(xiàn)Canny算法的原理和步驟,結(jié)合代碼示例和案例分析,展示了Canny算法在Java環(huán)境下的實(shí)現(xiàn)過程和邊緣檢測效果
    2024-11-11
  • SpringBoot內(nèi)部外部配置文件加載順序解析

    SpringBoot內(nèi)部外部配置文件加載順序解析

    這篇文章主要介紹了SpringBoot內(nèi)部外部配置文件加載順序解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • Java通俗易懂系列設(shè)計模式之模板模式

    Java通俗易懂系列設(shè)計模式之模板模式

    這篇文章主要介紹了Java通俗易懂系列設(shè)計模式之模板模式,想了解設(shè)計模式的同學(xué),可以仔細(xì)看一下
    2021-04-04
  • Spring?Boot集成JasperReport生成文檔的方法

    Spring?Boot集成JasperReport生成文檔的方法

    由于工作需要,要實(shí)現(xiàn)后端根據(jù)模板動態(tài)填充數(shù)據(jù)生成PDF文檔,通過技術(shù)選型,使用Ireport5.6來設(shè)計模板,結(jié)合JasperReports5.6工具庫來調(diào)用渲染生成PDF文檔,這篇文章主要介紹了Spring?Boot集成JasperReport生成文檔,需要的朋友可以參考下
    2023-09-09
  • SpringSecurity JWT基于令牌的無狀態(tài)認(rèn)證實(shí)現(xiàn)

    SpringSecurity JWT基于令牌的無狀態(tài)認(rèn)證實(shí)現(xiàn)

    Spring Security中實(shí)現(xiàn)基于JWT的無狀態(tài)認(rèn)證是一種常見的做法,本文就來介紹一下SpringSecurity JWT基于令牌的無狀態(tài)認(rèn)證實(shí)現(xiàn),感興趣的可以了解一下
    2025-04-04
  • mybatis Interceptor對UpdateTime自動處理的實(shí)現(xiàn)方法

    mybatis Interceptor對UpdateTime自動處理的實(shí)現(xiàn)方法

    這篇文章主要給大家介紹了關(guān)于使用mybatis Interceptor對UpdateTime自動處理的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧
    2018-12-12
  • django 遞歸查詢評論的示例詳解

    django 遞歸查詢評論的示例詳解

    文章介紹了將表數(shù)據(jù)轉(zhuǎn)換為樹狀結(jié)構(gòu)以及如何處理扁平化數(shù)據(jù)的方法,探討了在數(shù)據(jù)管理中的應(yīng)用和實(shí)現(xiàn)技術(shù),感興趣的朋友一起看看吧
    2025-01-01
  • 解決Error occurred during initialization of VM Java虛擬機(jī)初始化失敗問題

    解決Error occurred during initialization o

    這篇文章主要介紹了解決Error occurred during initialization of VM Java虛擬機(jī)初始化失敗問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Mybatis不啟動項(xiàng)目直接測試Mapper的實(shí)現(xiàn)方法

    Mybatis不啟動項(xiàng)目直接測試Mapper的實(shí)現(xiàn)方法

    在項(xiàng)目開發(fā)中,測試單個Mybatis Mapper方法通常需要啟動整個SpringBoot項(xiàng)目,消耗大量時間,本文介紹通過Main方法和Mybatis配置類,快速測試Mapper功能,無需啟動整個項(xiàng)目,這方法使用AnnotationConfigApplicationContext容器
    2024-09-09

最新評論

巴里| 米林县| 仙居县| 乳源| 葵青区| 丰原市| 耒阳市| 合川市| 车险| 宣武区| 读书| 新巴尔虎左旗| 大英县| 竹山县| 宁陕县| 恩施市| 和龙市| 苏尼特左旗| 凭祥市| 双辽市| 天门市| 疏附县| 冀州市| 高雄县| 洪洞县| 大厂| 灵台县| 无为县| 台东市| 石楼县| 沙河市| 封开县| 东乡族自治县| 雅江县| 三门峡市| 陆川县| 满洲里市| 玉屏| 漳平市| 和静县| 龙山县|