Java中的異步回調(diào)問題
有時(shí)候我們執(zhí)行一個(gè)任務(wù)需要很長(zhǎng)時(shí)間,單線程環(huán)境下 會(huì)處于阻塞狀態(tài),嚴(yán)重影響效率,那么可以使用一種非阻塞的處理方式,這就是使用多線程。
多線程情況下,問題出來了,我們不知道線程什么時(shí)候執(zhí)行完畢,或者不知道如何處理子線程的結(jié)果
那么就有以下兩種方式:異步回調(diào)和同步等待線程處理結(jié)果兩種方式
1. 異步回調(diào)
直接上代碼,固定格式:主業(yè)務(wù)代碼和一個(gè)處理結(jié)果的接口
/**
* Callback
* 回調(diào)一般是異步處理的一種技術(shù)。
* 一個(gè)回調(diào)是被傳遞到并且執(zhí)行完該方法。 這種方式只能異步回調(diào),
* 如果需要同步等待線程處理結(jié)果可以使用下面介紹的Futures
*/
interface MyCallback {
void doCallback(Map<String, Object> params);
}
public class TestAsyncCallBack {
static ExecutorService es = Executors.newFixedThreadPool(2);
public static void doSomething(MyCallback callback) {
// 初始化一個(gè)線程
Thread t = new Thread() {
public void run() {
// 這里是業(yè)務(wù)邏輯處理
System.out.println("子線任務(wù)開始執(zhí)行:" + Thread.currentThread().getId());
// 為了能看出效果 ,讓當(dāng)前線程阻塞5秒
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子線任務(wù)結(jié)束執(zhí)行:");
// 處理完業(yè)務(wù)邏輯,
Map<String, Object> params = new HashMap<String, Object>();
params.put("a1", "子線程處理結(jié)果");
callback.doCallback(params);
}
};
es.execute(t);
//一定要調(diào)用這個(gè)方法,不然executorService.isTerminated()永遠(yuǎn)不為true
es.shutdown();
}
public static void main(String[] args) {
// 內(nèi)部類 等價(jià)于 new MyCallBack(){...}, 主要作用就是重寫doCallback方法
doSomething((params) -> {
System.out.println("單個(gè)線程也已經(jīng)處理完畢了,返回參數(shù)a1=" + params.get("a1"));
});
System.out.println("主線任務(wù)已經(jīng)執(zhí)行完了:" + Thread.currentThread().getId());
}
}
2. 使用Future同步等待執(zhí)行結(jié)果
主要是利用了Callable接口開啟進(jìn)行多線程,call方法可以返回結(jié)果
/**
* Futures是一個(gè)抽象的概念,它表示一個(gè)值,該值可能在某一點(diǎn)變得可用。一個(gè)Future要么獲得計(jì)算完的結(jié)果,要么獲得計(jì)算失敗后的異常
* 每傳遞一個(gè)Runnable對(duì)象到ExecutorService.submit()方法就會(huì)得到一個(gè)回調(diào)的Future,你能使用它檢測(cè)是否執(zhí)行,這種方法可以是同步等待線處理結(jié)果
*/
public class TestFuture {
public static void main(String[] args) {
Callable<Result> callable = new Callable<Result>() {
@Override
public Result call() throws Exception {
//這里是業(yè)務(wù)邏輯處理
//讓當(dāng)前線程阻塞1秒看下效果
Thread.sleep(5000);
return new Result("張三");
}
};
ExecutorService executorService = Executors.newFixedThreadPool(5);
Future<Result> resultFuture = executorService.submit(callable);
executorService.shutdown();
/**
* 無限循環(huán)等待任務(wù)處理完畢 如果已經(jīng)處理完畢 isDone返回true
*/
while (!resultFuture.isDone()) {
try {
Result result = resultFuture.get(); // 在這一步阻塞知直到得到子線程返回結(jié)果
System.out.println(result.getName());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
class Result {
private String name;
public Result(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
javaweb實(shí)戰(zhàn)之商城項(xiàng)目開發(fā)(二)
這篇文章主要針對(duì)javaweb商城項(xiàng)目開發(fā)進(jìn)行實(shí)戰(zhàn)演習(xí),利用mybatis創(chuàng)建DAO層,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-02-02
Java垃圾回收機(jī)制的finalize方法實(shí)例分析
這篇文章主要介紹了Java垃圾回收機(jī)制的finalize方法,結(jié)合實(shí)例形式分析了finalize方法的特點(diǎn)及在垃圾回收機(jī)制中的相關(guān)操作技巧,需要的朋友可以參考下2019-08-08
Java多線程生產(chǎn)者消費(fèi)者模式實(shí)現(xiàn)過程解析
這篇文章主要介紹了Java多線程生產(chǎn)者消費(fèi)者模式實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
SpringBoot2零基礎(chǔ)到精通之映射與常用注解請(qǐng)求處理
SpringBoot是一種整合Spring技術(shù)棧的方式(或者說是框架),同時(shí)也是簡(jiǎn)化Spring的一種快速開發(fā)的腳手架,本篇讓我們一起學(xué)習(xí)映射、常用注解和方法參數(shù)的小技巧2022-03-03
Java SPI 機(jī)制知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理的是一篇關(guān)于Java SPI 機(jī)制知識(shí)點(diǎn)總結(jié)內(nèi)容,需要的朋友們可以參考下。2020-02-02
純Java環(huán)境下實(shí)現(xiàn)將在線地圖路網(wǎng)數(shù)據(jù)轉(zhuǎn)為GeoJSON與WKT
這篇文章主要為大家詳細(xì)介紹了如何純Java環(huán)境下實(shí)現(xiàn)將在線地圖路網(wǎng)數(shù)據(jù)轉(zhuǎn)為GeoJSON與WKT,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2026-02-02

