在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

CompletableFuture異步多線程是真的優雅

jf_ro2CN3Fa ? 來源:芋道源碼 ? 2023-08-07 15:40 ? 次閱讀

949e3ee8-34c2-11ee-9e74-dac502259ad0.gif

這是一個或許對你有用的開源項目

國產 Star 破 10w+ 的開源項目,前端包括管理后臺 + 微信小程序,后端支持單體和微服務架構。

功能涵蓋 RBAC 權限、SaaS 多租戶、數據權限、商城、支付、工作流、大屏報表、微信公眾號等等功能:

  • Boot 地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 地址:https://gitee.com/zhijiantianya/yudao-cloud
  • 視頻教程:https://doc.iocoder.cn

來源:后端元宇宙

  • 一個示例回顧Future
  • 通過CompletableFuture實現上面示例
  • CompletableFuture創建方式
  • 異步回調方法
  • 異常回調
  • 多任務組合回調
  • CompletableFuture使用有哪些注意點

952243f0-34c2-11ee-9e74-dac502259ad0.jpg


95379426-34c2-11ee-9e74-dac502259ad0.jpg

一個示例回顧Future

一些業務場景我們需要使用多線程異步執行任務,加快任務執行速度。

JDK5新增了Future接口,用于描述一個異步計算的結果。

雖然 Future 以及相關使用方法提供了異步執行任務的能力,但是對于結果的獲取卻是很不方便,我們必須使用Future.get()的方式阻塞調用線程,或者使用輪詢方式判斷 Future.isDone 任務是否結束,再獲取結果。

這兩種處理方式都不是很優雅,相關代碼如下:

@Test
publicvoidtestFuture()throwsExecutionException,InterruptedException{
ExecutorServiceexecutorService=Executors.newFixedThreadPool(5);
Futurefuture=executorService.submit(()->{
Thread.sleep(2000);
return"hello";
});
System.out.println(future.get());
System.out.println("end");
}

與此同時,Future無法解決多個異步任務需要相互依賴的場景,簡單點說就是,主線程需要等待子線程任務執行完畢之后在進行執行,這個時候你可能想到了CountDownLatch,沒錯確實可以解決,代碼如下。

這里定義兩個Future,第一個通過用戶id獲取用戶信息,第二個通過商品id獲取商品信息。

@Test
publicvoidtestCountDownLatch()throwsInterruptedException,ExecutionException{
ExecutorServiceexecutorService=Executors.newFixedThreadPool(5);
CountDownLatchdownLatch=newCountDownLatch(2);
longstartTime=System.currentTimeMillis();
FutureuserFuture=executorService.submit(()->{
//模擬查詢商品耗時500毫秒
Thread.sleep(500);
downLatch.countDown();
return"用戶A";
});

FuturegoodsFuture=executorService.submit(()->{
//模擬查詢商品耗時500毫秒
Thread.sleep(400);
downLatch.countDown();
return"商品A";
});

downLatch.await();
//模擬主程序耗時時間
Thread.sleep(600);
System.out.println("獲取用戶信息:"+userFuture.get());
System.out.println("獲取商品信息:"+goodsFuture.get());
System.out.println("總共用時"+(System.currentTimeMillis()-startTime)+"ms");

}

「運行結果」

獲取用戶信息:用戶A
獲取商品信息:商品A
總共用時1110ms

從運行結果可以看出結果都已經獲取,而且如果我們不用異步操作,執行時間應該是:500+400+600 = 1500,用異步操作后實際只用1110。

但是Java8以后我不在認為這是一種優雅的解決方式,接下來來了解下CompletableFuture的使用。

基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

  • 項目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 視頻教程:https://doc.iocoder.cn/video/

通過CompletableFuture實現上面示例

@Test
publicvoidtestCompletableInfo()throwsInterruptedException,ExecutionException{
longstartTime=System.currentTimeMillis();

//調用用戶服務獲取用戶基本信息
CompletableFutureuserFuture=CompletableFuture.supplyAsync(()->
//模擬查詢商品耗時500毫秒
{
try{
Thread.sleep(500);
}catch(InterruptedExceptione){
e.printStackTrace();
}
return"用戶A";
});

//調用商品服務獲取商品基本信息
CompletableFuturegoodsFuture=CompletableFuture.supplyAsync(()->
//模擬查詢商品耗時500毫秒
{
try{
Thread.sleep(400);
}catch(InterruptedExceptione){
e.printStackTrace();
}
return"商品A";
});

System.out.println("獲取用戶信息:"+userFuture.get());
System.out.println("獲取商品信息:"+goodsFuture.get());

//模擬主程序耗時時間
Thread.sleep(600);
System.out.println("總共用時"+(System.currentTimeMillis()-startTime)+"ms");
}

運行結果

獲取用戶信息:用戶A
獲取商品信息:商品A
總共用時1112ms

通過CompletableFuture可以很輕松的實現CountDownLatch的功能,你以為這就結束了,遠遠不止,CompletableFuture比這要強多了。

比如可以實現 :任務1執行完了再執行任務2,甚至任務1執行的結果,作為任務2的入參數等等強大功能,下面就來學學CompletableFuture的API

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

  • 項目地址:https://github.com/YunaiV/yudao-cloud
  • 視頻教程:https://doc.iocoder.cn/video/

CompletableFuture創建方式

1、常用的4種創建方式

CompletableFuture源碼中有四個靜態方法用來執行異步任務

publicstaticCompletableFuturesupplyAsync(Suppliersupplier){..}
publicstaticCompletableFuturesupplyAsync(Suppliersupplier,Executorexecutor){..}
publicstaticCompletableFuturerunAsync(Runnablerunnable){..}
publicstaticCompletableFuturerunAsync(Runnablerunnable,Executorexecutor){..}

一般我們用上面的靜態方法來創建CompletableFuture,這里也解釋下他們的區別:

  • 「supplyAsync」 執行任務,支持返回值。
  • 「runAsync」 執行任務,沒有返回值。

「supplyAsync方法」

//使用默認內置線程池ForkJoinPool.commonPool(),根據supplier構建執行任務
publicstaticCompletableFuturesupplyAsync(Suppliersupplier)
//自定義線程,根據supplier構建執行任務
publicstaticCompletableFuturesupplyAsync(Suppliersupplier,Executorexecutor)

「runAsync方法」

//使用默認內置線程池ForkJoinPool.commonPool(),根據runnable構建執行任務
publicstaticCompletableFuturerunAsync(Runnablerunnable)
//自定義線程,根據runnable構建執行任務
publicstaticCompletableFuturerunAsync(Runnablerunnable,Executorexecutor)

2、結果獲取的4種方式

對于結果的獲取CompltableFuture類提供了四種方式

//方式一
publicTget()
//方式二
publicTget(longtimeout,TimeUnitunit)
//方式三
publicTgetNow(TvalueIfAbsent)
//方式四
publicTjoin()

說明:

  • 「get()和get(long timeout, TimeUnit unit)」 => 在Future中就已經提供了,后者提供超時處理,如果在指定時間內未獲取結果將拋出超時異常
  • 「getNow」 => 立即獲取結果不阻塞,結果計算已完成將返回結果或計算過程中的異常,如果未計算完成將返回設定的valueIfAbsent值
  • 「join」 => 方法里不會拋出異常

示例:

@Test
publicvoidtestCompletableGet()throwsInterruptedException,ExecutionException{

CompletableFuturecp1=CompletableFuture.supplyAsync(()->{
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
return"商品A";
});

//getNow方法測試
System.out.println(cp1.getNow("商品B"));

//join方法測試
CompletableFuturecp2=CompletableFuture.supplyAsync((()->1/0));
System.out.println(cp2.join());
System.out.println("-----------------------------------------------------");
//get方法測試
CompletableFuturecp3=CompletableFuture.supplyAsync((()->1/0));
System.out.println(cp3.get());
}

「運行結果」

  • 第一個執行結果為 「商品B」 ,因為要先睡上1秒結果不能立即獲取
  • join方法獲取結果方法里不會拋異常,但是執行結果會拋異常,拋出的異常為CompletionException
  • get方法獲取結果方法里將拋出異常,執行結果拋出的異常為ExecutionException

異步回調方法

95657210-34c2-11ee-9e74-dac502259ad0.jpg

1、thenRun/thenRunAsync

通俗點講就是,「做完第一個任務后,再做第二個任務,第二個任務也沒有返回值」

示例

@Test
publicvoidtestCompletableThenRunAsync()throwsInterruptedException,ExecutionException{
longstartTime=System.currentTimeMillis();

CompletableFuturecp1=CompletableFuture.runAsync(()->{
try{
//執行任務A
Thread.sleep(600);
}catch(InterruptedExceptione){
e.printStackTrace();
}

});

CompletableFuturecp2=cp1.thenRun(()->{
try{
//執行任務B
Thread.sleep(400);
}catch(InterruptedExceptione){
e.printStackTrace();
}
});

//get方法測試
System.out.println(cp2.get());

//模擬主程序耗時時間
Thread.sleep(600);
System.out.println("總共用時"+(System.currentTimeMillis()-startTime)+"ms");
}

//運行結果
/**
*null
*總共用時1610ms
*/

「thenRun 和thenRunAsync有什么區別呢?」

如果你執行第一個任務的時候,傳入了一個自定義線程池:

  • 調用thenRun方法執行第二個任務時,則第二個任務和第一個任務是共用同一個線程池。
  • 調用thenRunAsync執行第二個任務時,則第一個任務使用的是你自己傳入的線程池,第二個任務使用的是ForkJoin線程池。

說明: 后面介紹的thenAcceptthenAcceptAsyncthenApplythenApplyAsync等,它們之間的區別也是這個。

2、thenAccept/thenAcceptAsync

第一個任務執行完成后,執行第二個回調方法任務,會將該任務的執行結果,作為入參 ,傳遞到回調方法中,但是回調方法是沒有返回值的。

示例
@Test
publicvoidtestCompletableThenAccept()throwsExecutionException,InterruptedException{
longstartTime=System.currentTimeMillis();
CompletableFuturecp1=CompletableFuture.supplyAsync(()->{
return"dev";

});
CompletableFuturecp2=cp1.thenAccept((a)->{
System.out.println("上一個任務的返回結果為:"+a);
});

cp2.get();
}

3、 thenApply/thenApplyAsync

表示第一個任務執行完成后,執行第二個回調方法任務,會將該任務的執行結果,作為入參,傳遞到回調方法中,并且回調方法是有返回值的。

示例

@Test
publicvoidtestCompletableThenApply()throwsExecutionException,InterruptedException{
CompletableFuturecp1=CompletableFuture.supplyAsync(()->{
return"dev";

}).thenApply((a)->{
if(Objects.equals(a,"dev")){
return"dev";
}
return"prod";
});

System.out.println("當前環境為:"+cp1.get());

//輸出:當前環境為:dev
}

異常回調

CompletableFuture的任務不論是正常完成還是出現異常它都會調用 「whenComplete」 這回調函數。

  • 「正常完成」 :whenComplete返回結果和上級任務一致,異常為null;
  • 「出現異常」 :whenComplete返回結果為null,異常為上級任務的異常;

即調用get()時,正常完成時就獲取到結果,出現異常時就會拋出異常,需要你處理該異常。

下面來看看示例

1、只用whenComplete

@Test
publicvoidtestCompletableWhenComplete()throwsExecutionException,InterruptedException{
CompletableFuturefuture=CompletableFuture.supplyAsync(()->{

if(Math.random()0.5){
thrownewRuntimeException("出錯了");
}
System.out.println("正常結束");
return0.11;

}).whenComplete((aDouble,throwable)->{
if(aDouble==null){
System.out.println("whenCompleteaDoubleisnull");
}else{
System.out.println("whenCompleteaDoubleis"+aDouble);
}
if(throwable==null){
System.out.println("whenCompletethrowableisnull");
}else{
System.out.println("whenCompletethrowableis"+throwable.getMessage());
}
});
System.out.println("最終返回的結果="+future.get());
}

正常完成,沒有異常時:

正常結束
whenCompleteaDoubleis0.11
whenCompletethrowableisnull
最終返回的結果=0.11

出現異常時:get()會拋出異常

whenCompleteaDoubleisnull
whenCompletethrowableisjava.lang.RuntimeException:出錯了

java.util.concurrent.ExecutionException:java.lang.RuntimeException:出錯了
atjava.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
atjava.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)

2、whenComplete + exceptionally示例

@Test
publicvoidtestWhenCompleteExceptionally()throwsExecutionException,InterruptedException{
CompletableFuturefuture=CompletableFuture.supplyAsync(()->{
if(Math.random()0.5){
thrownewRuntimeException("出錯了");
}
System.out.println("正常結束");
return0.11;

}).whenComplete((aDouble,throwable)->{
if(aDouble==null){
System.out.println("whenCompleteaDoubleisnull");
}else{
System.out.println("whenCompleteaDoubleis"+aDouble);
}
if(throwable==null){
System.out.println("whenCompletethrowableisnull");
}else{
System.out.println("whenCompletethrowableis"+throwable.getMessage());
}
}).exceptionally((throwable)->{
System.out.println("exceptionally中異常:"+throwable.getMessage());
return0.0;
});

System.out.println("最終返回的結果="+future.get());
}

當出現異常時,exceptionally中會捕獲該異常,給出默認返回值0.0。

whenCompleteaDoubleisnull
whenCompletethrowableisjava.lang.RuntimeException:出錯了
exceptionally中異常:java.lang.RuntimeException:出錯了
最終返回的結果=0.0

多任務組合回調

958594a0-34c2-11ee-9e74-dac502259ad0.jpg

1、AND組合關系

thenCombine / thenAcceptBoth / runAfterBoth都表示:「當任務一和任務二都完成再執行任務三」

區別在于:

  • 「runAfterBoth」 不會把執行結果當做方法入參,且沒有返回值
  • 「thenAcceptBoth」 : 會將兩個任務的執行結果作為方法入參,傳遞到指定方法中,且無返回值
  • 「thenCombine」 :會將兩個任務的執行結果作為方法入參,傳遞到指定方法中,且有返回值

示例

@Test
publicvoidtestCompletableThenCombine()throwsExecutionException,InterruptedException{
//創建線程池
ExecutorServiceexecutorService=Executors.newFixedThreadPool(10);
//開啟異步任務1
CompletableFuturetask=CompletableFuture.supplyAsync(()->{
System.out.println("異步任務1,當前線程是:"+Thread.currentThread().getId());
intresult=1+1;
System.out.println("異步任務1結束");
returnresult;
},executorService);

//開啟異步任務2
CompletableFuturetask2=CompletableFuture.supplyAsync(()->{
System.out.println("異步任務2,當前線程是:"+Thread.currentThread().getId());
intresult=1+1;
System.out.println("異步任務2結束");
returnresult;
},executorService);

//任務組合
CompletableFuturetask3=task.thenCombineAsync(task2,(f1,f2)->{
System.out.println("執行任務3,當前線程是:"+Thread.currentThread().getId());
System.out.println("任務1返回值:"+f1);
System.out.println("任務2返回值:"+f2);
returnf1+f2;
},executorService);

Integerres=task3.get();
System.out.println("最終結果:"+res);
}

「運行結果」

異步任務1,當前線程是:17
異步任務1結束
異步任務2,當前線程是:18
異步任務2結束
執行任務3,當前線程是:19
任務1返回值:2
任務2返回值:2
最終結果:4

2、OR組合關系

applyToEither / acceptEither / runAfterEither 都表示:「兩個任務,只要有一個任務完成,就執行任務三」

區別在于:

  • 「runAfterEither」 :不會把執行結果當做方法入參,且沒有返回值
  • 「acceptEither」 : 會將已經執行完成的任務,作為方法入參,傳遞到指定方法中,且無返回值
  • 「applyToEither」 :會將已經執行完成的任務,作為方法入參,傳遞到指定方法中,且有返回值

示例

@Test
publicvoidtestCompletableEitherAsync(){
//創建線程池
ExecutorServiceexecutorService=Executors.newFixedThreadPool(10);
//開啟異步任務1
CompletableFuturetask=CompletableFuture.supplyAsync(()->{
System.out.println("異步任務1,當前線程是:"+Thread.currentThread().getId());

intresult=1+1;
System.out.println("異步任務1結束");
returnresult;
},executorService);

//開啟異步任務2
CompletableFuturetask2=CompletableFuture.supplyAsync(()->{
System.out.println("異步任務2,當前線程是:"+Thread.currentThread().getId());
intresult=1+2;
try{
Thread.sleep(3000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
System.out.println("異步任務2結束");
returnresult;
},executorService);

//任務組合
task.acceptEitherAsync(task2,(res)->{
System.out.println("執行任務3,當前線程是:"+Thread.currentThread().getId());
System.out.println("上一個任務的結果為:"+res);
},executorService);
}

運行結果

//通過結果可以看出,異步任務2都沒有執行結束,任務3獲取的也是1的執行結果
異步任務1,當前線程是:17
異步任務1結束
異步任務2,當前線程是:18
執行任務3,當前線程是:19
上一個任務的結果為:2

注意

如果把上面的核心線程數改為1也就是

ExecutorServiceexecutorService=Executors.newFixedThreadPool(1);

運行結果就是下面的了,會發現根本沒有執行任務3,顯然是任務3直接被丟棄了。

異步任務1,當前線程是:17
異步任務1結束
異步任務2,當前線程是:17

3、多任務組合

  • 「allOf」 :等待所有任務完成
  • 「anyOf」 :只要有一個任務完成

示例

allOf:等待所有任務完成

@Test
publicvoidtestCompletableAallOf()throwsExecutionException,InterruptedException{
//創建線程池
ExecutorServiceexecutorService=Executors.newFixedThreadPool(10);
//開啟異步任務1
CompletableFuturetask=CompletableFuture.supplyAsync(()->{
System.out.println("異步任務1,當前線程是:"+Thread.currentThread().getId());
intresult=1+1;
System.out.println("異步任務1結束");
returnresult;
},executorService);

//開啟異步任務2
CompletableFuturetask2=CompletableFuture.supplyAsync(()->{
System.out.println("異步任務2,當前線程是:"+Thread.currentThread().getId());
intresult=1+2;
try{
Thread.sleep(3000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
System.out.println("異步任務2結束");
returnresult;
},executorService);

//開啟異步任務3
CompletableFuturetask3=CompletableFuture.supplyAsync(()->{
System.out.println("異步任務3,當前線程是:"+Thread.currentThread().getId());
intresult=1+3;
try{
Thread.sleep(4000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
System.out.println("異步任務3結束");
returnresult;
},executorService);

//任務組合
CompletableFutureallOf=CompletableFuture.allOf(task,task2,task3);

//等待所有任務完成
allOf.get();
//獲取任務的返回結果
System.out.println("task結果為:"+task.get());
System.out.println("task2結果為:"+task2.get());
System.out.println("task3結果為:"+task3.get());
}

anyOf: 只要有一個任務完成

@Test
publicvoidtestCompletableAnyOf()throwsExecutionException,InterruptedException{
//創建線程池
ExecutorServiceexecutorService=Executors.newFixedThreadPool(10);
//開啟異步任務1
CompletableFuturetask=CompletableFuture.supplyAsync(()->{
intresult=1+1;
returnresult;
},executorService);

//開啟異步任務2
CompletableFuturetask2=CompletableFuture.supplyAsync(()->{
intresult=1+2;
returnresult;
},executorService);

//開啟異步任務3
CompletableFuturetask3=CompletableFuture.supplyAsync(()->{
intresult=1+3;
returnresult;
},executorService);

//任務組合
CompletableFutureanyOf=CompletableFuture.anyOf(task,task2,task3);
//只要有一個有任務完成
Objecto=anyOf.get();
System.out.println("完成的任務的結果:"+o);
}

			

CompletableFuture使用有哪些注意點

95a77c46-34c2-11ee-9e74-dac502259ad0.jpg

CompletableFuture 使我們的異步編程更加便利的、代碼更加優雅的同時,我們也要關注下它,使用的一些注意點。

1、Future需要獲取返回值,才能獲取異常信息

@Test
publicvoidtestWhenCompleteExceptionally(){
CompletableFuturefuture=CompletableFuture.supplyAsync(()->{
if(1==1){
thrownewRuntimeException("出錯了");
}
return0.11;
});

//如果不加get()方法這一行,看不到異常信息
//future.get();
}

Future需要獲取返回值,才能獲取到異常信息。如果不加 get()/join()方法,看不到異常信息。

小伙伴們使用的時候,注意一下哈,考慮是否加try...catch...或者使用exceptionally方法。

2、CompletableFuture的get()方法是阻塞的

CompletableFutureget()方法是阻塞的,如果使用它來獲取異步調用的返回值,需要添加超時時間。

//反例
CompletableFuture.get();
//正例
CompletableFuture.get(5,TimeUnit.SECONDS);

3、不建議使用默認線程池

CompletableFuture代碼中又使用了默認的 「ForkJoin線程池」 ,處理的線程個數是電腦 CPU核數-1」 。在大量請求過來的時候,處理邏輯復雜的話,響應會很慢。一般建議使用自定義線程池,優化線程池配置參數。

4、自定義線程池時,注意飽和策略

CompletableFuture的get()方法是阻塞的,我們一般建議使用future.get(5, TimeUnit.SECONDS)。并且一般建議使用自定義線程池。

但是如果線程池拒絕策略是DiscardPolicy或者DiscardOldestPolicy,當線程池飽和時,會直接丟棄任務,不會拋棄異常。因此建議,CompletableFuture線程池策略最好使用AbortPolicy,然后耗時的異步線程,做好線程池隔離哈。


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 代碼
    +關注

    關注

    30

    文章

    4788

    瀏覽量

    68612
  • 異步
    +關注

    關注

    0

    文章

    62

    瀏覽量

    18050
  • 線程
    +關注

    關注

    0

    文章

    504

    瀏覽量

    19683

原文標題:奇淫巧技,CompletableFuture 異步多線程是真的優雅

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Java多線程的用法

    本文將介紹一下Java多線程的用法。 基礎介紹 什么是多線程 指的是在一個進程中同時運行多個線程,每個線程都可以獨立執行不同的任務或操作。 與單線程
    的頭像 發表于 09-30 17:07 ?953次閱讀

    想學labview異步多線程,大型項目規范,各類通訊的找我

    想學labview異步多線程,大型項目規范,各類通訊的找我,qq***
    發表于 02-27 21:19

    如何使用多線程異步操作等并發設計方法來最大化程序的性能

      異步多線程的區別  一、異步多線程有什么區別?其實,異步是目的,而多線程是實現這個目的的
    發表于 08-23 16:31

    LabWindows_CVI多線程技術的應用研究

    分析了線程與進程的關系,研究了LabWindows/CVI多線程技術運行機制及其數據保護機制,對利用異步定時器實現的多線程軟件與傳統單線程
    發表于 08-29 14:53 ?68次下載
    LabWindows_CVI<b class='flag-5'>多線程</b>技術的應用研究

    多線程好還是單線程好?單線程多線程的區別 優缺點分析

    摘要:如今單線程多線程已經得到普遍運用,那么到底多線程好還是單線程好呢?單線程多線程的區別又
    發表于 12-08 09:33 ?8.1w次閱讀

    mfc多線程編程實例及代碼,mfc多線程間通信介紹

    摘要:本文主要以MFC多線程為中心,分別對MFC多線程的實例、MFC多線程之間的通信展開的一系列研究,下面我們來看看原文。
    發表于 12-08 15:23 ?1.8w次閱讀
    mfc<b class='flag-5'>多線程</b>編程實例及代碼,mfc<b class='flag-5'>多線程</b>間通信介紹

    什么是多線程編程?多線程編程基礎知識

    摘要:多線程編程是現代軟件技術中很重要的一個環節。要弄懂多線程,這就要牽涉到多進程。本文主要以多線程編程以及多線程編程相關知識而做出的一些結論。
    發表于 12-08 16:30 ?1.3w次閱讀

    Java多線程永動任務 多線程異步任務項目解讀

    , 這個示例的原型是公司自研的多線程異步任務項目 ,我把里面涉及到多線程的代碼抽離出來,然后進行一定的改造。 里面涉及的知識點非常多,特別適合有 一定工作經驗 的同學學習,或者可以直接拿到項目中使用。 文章結構非常簡單: 1.
    的頭像 發表于 10-19 11:46 ?1125次閱讀

    SpringBoot實現多線程

    SpringBoot實現多線程
    的頭像 發表于 01-12 16:59 ?1831次閱讀
    SpringBoot實現<b class='flag-5'>多線程</b>

    labview AMC多線程

    labview_AMC多線程
    發表于 08-21 10:31 ?32次下載

    多線程如何保證數據的同步

    多線程編程是一種并發編程的方法,意味著程序中同時運行多個線程,每個線程可獨立執行不同的任務,共享同一份數據。由于多線程并發執行的特點,會引發數據同步的問題,即保證多個
    的頭像 發表于 11-17 14:22 ?1235次閱讀

    mfc多線程編程實例

    (圖形用戶界面)應用程序的開發。在這篇文章中,我們將重點介紹MFC中的多線程編程。 多線程編程在軟件開發中非常重要,它可以實現程序的并發執行,提高程序的效率和響應速度。MFC提供了豐富的多線程支持,可以輕松地實現
    的頭像 發表于 12-01 14:29 ?1507次閱讀

    java實現多線程的幾種方式

    CompletableFuture 一、繼承Thread類 繼承Thread類是實現多線程的最基本方式,只需創建一個類并繼承Thread類,重寫run()方法即可。 ``
    的頭像 發表于 03-14 16:55 ?709次閱讀

    多線程設計模式到對 CompletableFuture 的應用

    最近在開發 延保服務 頻道頁時,為了提高查詢效率,使用到了多線程技術。為了對多線程方案設計有更加充分的了解,在業余時間讀完了《圖解 Java 多線程設計模式》這本書,覺得收獲良多。本篇文章將介紹其中
    的頭像 發表于 06-26 14:18 ?363次閱讀
    從<b class='flag-5'>多線程</b>設計模式到對 <b class='flag-5'>CompletableFuture</b> 的應用

    Java CompletableFuture 異步超時實現探索

    用手段便是多線程并行執行。這時候就會涉及到 CompletableFuture 的使用。 常見使用方式 下面舉例一個常見場景。
    的頭像 發表于 07-25 14:06 ?371次閱讀
    主站蜘蛛池模板: 可以免费看黄的网站| 视频在线观看网站免费| 久久综合九色综合98一99久久99久| 女人夜夜春| 午夜影院在线观看免费| 啪啪免费看视频| 天天色爱| 日韩精品一级a毛片| 久久看免费视频| 天天搞夜夜爽| 欧美一区亚洲| 五月婷婷在线观看| 免费四虎永久在线精品| 丁香5月婷婷| 欧美黄色录象| 国产精品爱久久久久久久三级| 欧美精品四虎在线观看| aaaaaa级特色特黄的毛片| 免费视频一级片| 中韩日欧美电影免费看| 精品一区二区三区免费爱| 青青青久97在线观看香蕉| 9久久99久久久精品齐齐综合色圆| 色在线网站免费观看| 黄色伊人| 日夜操在线视频| 国产99热| 国产成人精品日本亚洲语言| 女bbbbxxxx另类亚洲| 综合五月婷婷| 成人亚洲电影| 中文字幕一区二区三区在线不卡| 日本高清网站| 夜夜草天天干| 欧美性第一页| 五月婷婷色视频| 夜夜做夜夜爽| 九月婷婷综合婷婷| 国产成人小视频| 亚洲欧美日韩特级毛片| 色噜噜狠狠色综合欧洲selulu|