电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Java異步調(diào)用轉(zhuǎn)同步方法實例詳解

瀏覽:36日期:2022-08-30 13:02:27

先說一下對異步和同步的理解:

同步調(diào)用:調(diào)用方在調(diào)用過程中,持續(xù)等待返回結果。

異步調(diào)用:調(diào)用方在調(diào)用過程中,不直接等待返回結果,而是執(zhí)行其他任務,結果返回形式通常為回調(diào)函數(shù)。

其實,兩者的區(qū)別還是很明顯的,這里也不再細說,我們主要來說一下Java如何將異步調(diào)用轉(zhuǎn)為同步。換句話說,就是需要在異步

調(diào)用過程中,持續(xù)阻塞至獲得調(diào)用結果。

不賣關子,先列出五種方法,然后一一舉例說明:

使用wait和notify方法 使用條件鎖 Future 使用CountDownLatch 使用CyclicBarrier

0.構造一個異步調(diào)用

首先,寫demo需要先寫基礎設施,這里的話主要是需要構造一個異步調(diào)用模型。異步調(diào)用類:

public class AsyncCall { private Random random = new Random(System.currentTimeMillis()); private ExecutorService tp = Executors.newSingleThreadExecutor(); //demo1,2,4,5調(diào)用方法 public void call(BaseDemo demo){ new Thread(()->{ long res = random.nextInt(10); try {Thread.sleep(res*1000); } catch (InterruptedException e) {e.printStackTrace(); } demo.callback(res); }).start(); } //demo3調(diào)用方法 public Future<Long> futureCall(){ return tp.submit(()-> { long res = random.nextInt(10); try {Thread.sleep(res*1000); } catch (InterruptedException e) {e.printStackTrace(); } return res; }); } public void shutdown(){ tp.shutdown(); }}

我們主要關心call方法,這個方法接收了一個demo參數(shù),并且開啟了一個線程,在線程中執(zhí)行具體的任務,并利用demo的callback方法進行回調(diào)函數(shù)的調(diào)用。大家注意到了這里的返回結果就是一個[0,10)的長整型,并且結果是幾,就讓線程sleep多久——這主要是為了更好地觀察實驗結果,模擬異步調(diào)用過程中的處理時間。至于futureCall和shutdown方法,以及線程池tp都是為了demo3利用Future來實現(xiàn)做準備的。

demo的基類:

public abstract class BaseDemo { protected AsyncCall asyncCall = new AsyncCall(); public abstract void callback(long response); public void call(){ System.out.println('發(fā)起調(diào)用'); asyncCall.call(this); System.out.println('調(diào)用返回'); }}

BaseDemo非常簡單,里面包含一個異步調(diào)用類的實例,另外有一個call方法用于發(fā)起異步調(diào)用,當然還有一個抽象方法callback需要每個demo去實現(xiàn)的——主要在回調(diào)中進行相應的處理來達到異步調(diào)用轉(zhuǎn)同步的目的。

1. 使用wait和notify方法

這個方法其實是利用了鎖機制,直接貼代碼:

public class Demo1 extends BaseDemo{ private final Object lock = new Object(); @Override public void callback(long response) { System.out.println('得到結果'); System.out.println(response); System.out.println('調(diào)用結束'); synchronized (lock) { lock.notifyAll(); } } public static void main(String[] args) { Demo1 demo1 = new Demo1(); demo1.call(); synchronized (demo1.lock){ try {demo1.lock.wait(); } catch (InterruptedException e) {e.printStackTrace(); } } System.out.println('主線程內(nèi)容'); }}

可以看到在發(fā)起調(diào)用后,主線程利用wait進行阻塞,等待回調(diào)中調(diào)用notify或者notifyAll方法來進行喚醒。注意,和大家認知的一樣,這里wait和notify都是需要先獲得對象的鎖的。在主線程中最后我們打印了一個內(nèi)容,這也是用來驗證實驗結果的,如果沒有wait和notify,主線程內(nèi)容會緊隨調(diào)用內(nèi)容立刻打?。欢裎覀兩厦娴拇a,主線程內(nèi)容會一直等待回調(diào)函數(shù)調(diào)用結束才會進行打印。

沒有使用同步操作的情況下,打印結果:

發(fā)起調(diào)用調(diào)用返回主線程內(nèi)容得到結果1調(diào)用結束

而使用了同步操作后:

發(fā)起調(diào)用調(diào)用返回得到結果9調(diào)用結束主線程內(nèi)容

2. 使用條件鎖

和方法一的原理類似:

public class Demo2 extends BaseDemo { private final Lock lock = new ReentrantLock(); private final Condition con = lock.newCondition(); @Override public void callback(long response) { System.out.println('得到結果'); System.out.println(response); System.out.println('調(diào)用結束'); lock.lock(); try { con.signal(); }finally { lock.unlock(); } } public static void main(String[] args) { Demo2 demo2 = new Demo2(); demo2.call(); demo2.lock.lock(); try { demo2.con.await(); } catch (InterruptedException e) { e.printStackTrace(); }finally { demo2.lock.unlock(); } System.out.println('主線程內(nèi)容'); }}

基本上和方法一沒什么區(qū)別,只是這里使用了條件鎖,兩者的鎖機制有所不同。

3. Future

使用Future的方法和之前不太一樣,我們調(diào)用的異步方法也不一樣。

public class Demo3{ private AsyncCall asyncCall = new AsyncCall(); public Future<Long> call(){ Future<Long> future = asyncCall.futureCall(); asyncCall.shutdown(); return future; } public static void main(String[] args) { Demo3 demo3 = new Demo3(); System.out.println('發(fā)起調(diào)用'); Future<Long> future = demo3.call(); System.out.println('返回結果'); while (!future.isDone() && !future.isCancelled()); try { System.out.println(future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println('主線程內(nèi)容'); }}

我們調(diào)用futureCall方法,方法中會想線程池tp提交一個Callable,然后返回一個Future,這個Future就是我們demo3中call中得到的,得到future對象之后就可以關閉線程池啦,調(diào)用asyncCall的shutdown方法。關于關閉線程池這里有一點需要注意,我們回過頭來看看asyncCall的shutdown方法:

public void shutdown(){ tp.shutdown(); }

發(fā)現(xiàn)只是簡單調(diào)用了線程池的shutdown方法,然后我們說注意的點,這里最好不要用tp的shutdownNow方法,該方法會試圖去中斷線程中中正在執(zhí)行的任務;也就是說,如果使用該方法,有可能我們的future所對應的任務將被中斷,無法得到執(zhí)行結果。然后我們關注主線程中的內(nèi)容,主線程的阻塞由我們自己來實現(xiàn),通過future的isDone和isCancelled來判斷執(zhí)行狀態(tài),一直到執(zhí)行完成或被取消。隨后,我們打印get到的結果。

4. 使用CountDownLatch

使用CountDownLatch或許是日常編程中最常見的一種了,也感覺是相對優(yōu)雅的一種:

public class Demo4 extends BaseDemo{ private final CountDownLatch countDownLatch = new CountDownLatch(1); @Override public void callback(long response) { System.out.println('得到結果'); System.out.println(response); System.out.println('調(diào)用結束'); countDownLatch.countDown(); } public static void main(String[] args) { Demo4 demo4 = new Demo4(); demo4.call(); try { demo4.countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println('主線程內(nèi)容'); }}

正如大家平時使用的那樣,此處在主線程中利用CountDownLatch的await方法進行阻塞,在回調(diào)中利用countDown方法來使得其他線程await的部分得以繼續(xù)運行。

當然,這里和demo1和demo2中都一樣,主線程中阻塞的部分,都可以設置一個超時時間,超時后可以不再阻塞。

5. 使用CyclicBarrier

public class Demo5 extends BaseDemo{ private CyclicBarrier cyclicBarrier = new CyclicBarrier(2); @Override public void callback(long response) { System.out.println('得到結果'); System.out.println(response); System.out.println('調(diào)用結束'); try { cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } public static void main(String[] args) { Demo5 demo5 = new Demo5(); demo5.call(); try { demo5.cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println('主線程內(nèi)容'); }}

大家注意一下,CyclicBarrier和CountDownLatch僅僅只是類似,兩者還是有一定區(qū)別的。比如,一個可以理解為做加法,等到加到這個數(shù)字后一起運行;一個則是減法,減到0繼續(xù)運行。一個是可以重復計數(shù)的;另一個不可以等等等等。

另外,使用CyclicBarrier的時候要注意兩點。第一點,初始化的時候,參數(shù)數(shù)字要設為2,因為異步調(diào)用這里是一個線程,而主線程是一個線程,兩個線程都await的時候才能繼續(xù)執(zhí)行,這也是和CountDownLatch區(qū)別的部分。第二點,也是關于初始化參數(shù)的數(shù)值的,和這里的demo無關,在平時編程的時候,需要比較小心,如果這個數(shù)值設置得很大,比線程池中的線程數(shù)都大,那么就很容易引起死鎖了。

總結

綜上,就是本次需要說的幾種方法了。事實上,所有的方法都是同一個原理,也就是在調(diào)用的線程中進行阻塞等待結果,而在回調(diào)中函數(shù)中進行阻塞狀態(tài)的解除。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標簽: Java
相關文章:
主站蜘蛛池模板: 九州网址_专注于提供网址大全分享推广中文网站导航服务 | 合肥汽车充电桩_安徽充电桩_电动交流充电桩厂家_安徽科帝新能源科技有限公司 | 氧氮氢联合测定仪-联测仪-氧氮氢元素分析仪-江苏品彦光电 | 博医通医疗器械互联网供应链服务平台_博医通 | 粉丝机械,粉丝烘干机,粉丝生产线-招远市远东粉丝机械有限公司 | 高低温试验箱-模拟高低温试验箱订制-北京普桑达仪器科技有限公司【官网】 | 广州中央空调回收,二手中央空调回收,旧空调回收,制冷设备回收,冷气机组回收公司-广州益夫制冷设备回收公司 | 两头忙,井下装载机,伸缩臂装载机,30装载机/铲车,50装载机/铲车厂家_价格-莱州巨浪机械有限公司 | PTFE接头|聚四氟乙烯螺丝|阀门|薄膜|消解罐|聚四氟乙烯球-嘉兴市方圆氟塑制品有限公司 | RTO换向阀_VOC高温阀门_加热炉切断阀_双偏心软密封蝶阀_煤气蝶阀_提升阀-湖北霍科德阀门有限公司 | 贝朗斯动力商城(BRCPOWER.COM) - 买叉车蓄电池上贝朗斯商城,价格更超值,品质有保障! | 重庆波纹管|重庆钢带管|重庆塑钢管|重庆联进管道有限公司 | ?水马注水围挡_塑料注水围挡_防撞桶-常州瑞轩水马注水围挡有限公司 | 河北凯普威医疗器材有限公司,高档轮椅系列,推车系列,座厕椅系列,协步椅系列,拐扙系列,卫浴系列 | 广州企亚 - 数码直喷、白墨印花、源头厂家、透气无手感方案服务商! | 兰州UPS电源,兰州山特UPS-兰州万胜商贸 | 培训中心-海南香蕉蛋糕加盟店技术翰香原中心官网总部 | 根系分析仪,大米外观品质检测仪,考种仪,藻类鉴定计数仪,叶面积仪,菌落计数仪,抑菌圈测量仪,抗生素效价测定仪,植物表型仪,冠层分析仪-杭州万深检测仪器网 | 鑫达滑石-辽宁鑫达滑石集团 | 喷涂流水线,涂装流水线,喷漆流水线-山东天意设备科技有限公司 | 气弹簧定制-气动杆-可控气弹簧-不锈钢阻尼器-工业气弹簧-可调节气弹簧厂家-常州巨腾气弹簧供应商 | 动库网动库商城-体育用品专卖店:羽毛球,乒乓球拍,网球,户外装备,运动鞋,运动包,运动服饰专卖店-正品运动品网上商城动库商城网 - 动库商城 | 书法培训-高考书法艺考培训班-山东艺霖书法培训凭实力挺进央美 | 中央空调维修、中央空调保养、螺杆压缩机维修-苏州东菱空调 | 无锡不干胶标签,卷筒标签,无锡瑞彩包装材料有限公司 | 济南ISO9000认证咨询代理公司,ISO9001认证,CMA实验室认证,ISO/TS16949认证,服务体系认证,资产管理体系认证,SC食品生产许可证- 济南创远企业管理咨询有限公司 郑州电线电缆厂家-防火|低压|低烟无卤电缆-河南明星电缆 | 液氮罐_液氮容器_自增压液氮罐_杜瓦瓶_班德液氮罐厂家 | 升降机-高空作业车租赁-蜘蛛车-曲臂式伸缩臂剪叉式液压升降平台-脚手架-【普雷斯特公司厂家】 | 振动传感器,检波器-威海广达勘探仪器有限公司 | 环压强度试验机-拉链拉力试验机-上海倾技仪器仪表科技有限公司 | 杭州标识标牌|文化墙|展厅|导视|户内外广告|发光字|灯箱|铭阳制作公司 - 杭州标识标牌|文化墙|展厅|导视|户内外广告|发光字|灯箱|铭阳制作公司 | 纳米二氧化硅,白炭黑,阴离子乳化剂-臻丽拾科技 | 物联网卡_物联网卡购买平台_移动物联网卡办理_移动联通电信流量卡通信模组采购平台? | 佛山市钱丰金属不锈钢蜂窝板定制厂家|不锈钢装饰线条|不锈钢屏风| 电梯装饰板|不锈钢蜂窝板不锈钢工艺板材厂家佛山市钱丰金属制品有限公司 | 楼承板-开闭口楼承板-无锡海逵楼承板| 重庆LED显示屏_显示屏安装公司_重庆LED显示屏批发-彩光科技公司 重庆钣金加工厂家首页-专业定做监控电视墙_操作台 | 【黄页88网】-B2B电子商务平台,b2b平台免费发布信息网 | 地图标注|微信高德百度地图标注|地图标记-做地图[ZuoMap.com] | 中原网视台| 密集架-手摇-智能-移动-价格_内蒙古档案密集架生产厂家 | 超声波_清洗机_超声波清洗机专业生产厂家-深圳市好顺超声设备有限公司 |