Java中5種異步實(shí)現(xiàn)的方式詳解_第1頁
Java中5種異步實(shí)現(xiàn)的方式詳解_第2頁
Java中5種異步實(shí)現(xiàn)的方式詳解_第3頁
Java中5種異步實(shí)現(xiàn)的方式詳解_第4頁
Java中5種異步實(shí)現(xiàn)的方式詳解_第5頁
已閱讀5頁,還剩2頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第Java中5種異步實(shí)現(xiàn)的方式詳解目錄一、什么是異步二、線程異步三、Future異步四、CompletableFuture異步五、SpringBoot@Async異步六、Guava異步

一、什么是異步

首先我們先來看看一個(gè)同步的用戶注冊例子,流程如下:

在同步操作中,我們執(zhí)行到插入數(shù)據(jù)庫的時(shí)候,我們必須等待這個(gè)方法徹底執(zhí)行完才能執(zhí)行發(fā)送短信這個(gè)操作,如果插入數(shù)據(jù)庫這個(gè)動(dòng)作執(zhí)行時(shí)間較長,發(fā)送短信需要等待,這就是典型的同步場景。

于是聰明的人們開始思考,如果兩者關(guān)聯(lián)性不強(qiáng),能不能將一些非核心業(yè)務(wù)從主流程中剝離出來,于是有了異步編程雛形,改進(jìn)后的流程如下:

這就是異步編程,它是程序并發(fā)運(yùn)行的一種手段,它允許多個(gè)事件同時(shí)發(fā)生,當(dāng)程序調(diào)用需要長時(shí)間運(yùn)行的方法時(shí),它不會(huì)阻塞當(dāng)前的執(zhí)行流程,程序可以繼續(xù)運(yùn)行。

在聊完異步編程后,那么我們一起來看看Java里面實(shí)現(xiàn)異步編程究竟有哪些方式呢?

二、線程異步

在Java語言中最簡單使用異步編程的方式就是創(chuàng)建一個(gè)線程來實(shí)現(xiàn),如果你使用的JDK版本是8以上的話,可以使用Lambda表達(dá)式會(huì)更加簡潔。

publicclassAsyncThreadextendsThread{

@Override

publicvoidrun(){

System.out.println("當(dāng)前線程名稱:"+this.getName()+",執(zhí)行線程名稱:"+Thread.currentThread().getName()+"-hello");

publicstaticvoidmain(String[]args){

//模擬業(yè)務(wù)流程

//.......

//創(chuàng)建異步線程

AsyncThreadasyncThread=newAsyncThread();

//啟動(dòng)異步線程

asyncThread.start();

}

當(dāng)然如果每次都創(chuàng)建一個(gè)Thread線程,頻繁的創(chuàng)建、銷毀,浪費(fèi)系統(tǒng)資源,我們可以采用線程池:

privateExecutorServiceexecutor=Executors.newCachedThreadPool();

publicvoidfun()throwsException{

executor.submit(newRunnable(){

@override

publicvoidrun(){

try{

//要執(zhí)行的業(yè)務(wù)代碼,我們這里沒有寫方法,可以讓線程休息幾秒進(jìn)行測試

Thread.sleep(10000);

System.out.print("睡夠啦~");

}catch(Exceptione){

thrownewRuntimeException("報(bào)錯(cuò)啦?。?);

將業(yè)務(wù)邏輯封裝到Runnable或Callable中,交由線程池來執(zhí)行。

三、Future異步

上述方式雖然達(dá)到了多線程并行處理,但有些業(yè)務(wù)不僅僅要執(zhí)行過程,還要獲取執(zhí)行結(jié)果,后續(xù)提供在JUC包增加了Future。

從字面意思理解就是未來的意思,但使用起來卻著實(shí)有點(diǎn)雞肋,并不能實(shí)現(xiàn)真正意義上的異步,獲取結(jié)果時(shí)需要阻塞線程,或者不斷輪詢。

@Test

publicvoidfutureTest()throwsException{

System.out.println("main函數(shù)開始執(zhí)行");

ExecutorServiceexecutor=Executors.newFixedThreadPool(1);

FutureIntegerfuture=executor.submit(newCallableInteger(){

@Override

publicIntegercall()throwsException{

System.out.println("===taskstart===");

Thread.sleep(5000);

System.out.println("===taskfinish===");

return3;

//這里需要返回值時(shí)會(huì)阻塞主線程,如果不需要返回值使用是OK的。倒也還能接收

//Integerresult=future.get();

System.out.println("main函數(shù)執(zhí)行結(jié)束");

System.in.read();

}

四、CompletableFuture異步

Future類通過get()方法阻塞等待獲取異步執(zhí)行的運(yùn)行結(jié)果,性能比較差。

JDK1.8中,Java提供了CompletableFuture類,它是基于異步函數(shù)式編程。相對(duì)阻塞式等待返回結(jié)果,CompletableFuture可以通過回調(diào)的方式來處理計(jì)算結(jié)果,實(shí)現(xiàn)了異步非阻塞,性能更優(yōu)。

CompletableFuture實(shí)現(xiàn)了Future和CompletionStage接口,并提供了多種實(shí)現(xiàn)異步編程的方法,如supplyAsync,runAsync以及thenApplyAsync。

下面我們使用CompletableFuture來實(shí)現(xiàn)上面的例子:

CompletableFutureLongcompletableFuture=CompletableFuture.supplyAsync(()-factorial(number));

while(!completableFuture.isDone()){

System.out.println("CompletableFutureisnotfinishedyet...");

longresult=completableFuture.get();

我們不需要顯式使用ExecutorService,CompletableFuture內(nèi)部使用了ForkJoinPool來處理異步任務(wù),這使得我們的代碼變的更簡潔。

五、SpringBoot@Async異步

在@Async注解之前,使用多線程需要使用JDK的原生方法,非常麻煩,當(dāng)有了@Async之后就比較簡單了。

首先,使用@EnableAsync啟用異步注解:

@SpringBootApplication

@EnableAsync

publicclassStartApplication{

publicstaticvoidmain(String[]args){

SpringApplication.run(StartApplication.class,args);

}

自定義線程池:

@Configuration

@Slf4j

publicclassThreadPoolConfiguration{

@Bean(name="defaultThreadPoolExecutor",destroyMethod="shutdown")

publicThreadPoolExecutorsystemCheckPoolExecutorService(){

returnnewThreadPoolExecutor(3,10,60,TimeUnit.SECONDS,

newLinkedBlockingQueueRunnable(10000),

newThreadFactoryBuilder().setNameFormat("default-executor-%d").build(),

(r,executor)-log.error("systempoolisfull!"));

}

在異步處理的方法上添加注解@Async,當(dāng)對(duì)execute方法調(diào)用時(shí),通過自定義的線程池defaultThreadPoolExecutor異步化執(zhí)行execute方法

@Service

publicclassAsyncServiceImplimplementsAsyncService{

@Async("defaultThreadPoolExecutor")

publicBooleanexecute(Integernum){

System.out.println("線程:"+Thread.currentThread().getName()+",任務(wù):"+num);

returntrue;

}

用@Async注解標(biāo)記的方法,稱為異步方法。在springboot應(yīng)用中使用@Async很簡單:

調(diào)用異步方法類上或者啟動(dòng)類加上注解@EnableAsync在需要被異步調(diào)用的方法外加上@Async所使用的@Async注解方法的類對(duì)象應(yīng)該是Spring容器管理的bean對(duì)象;

六、Guava異步

Guava提供了ListenableFuture類來執(zhí)行異步操作

1.首先我們需要添加guava的maven依賴:

dependency

groupIdcom.google.guava/groupId

artifactIdguava/artifactId

version28.2-jre/version

/dependency

2.現(xiàn)在我們使用ListenableFuture來實(shí)現(xiàn)我們之前的例子:

ExecutorServicethreadpool=Executors.newCachedThreadPool();

ListeningExecutorServiceservice=MoreExecutors.listeningDecorator(threadpool);

ListenableFutureLon

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論