当前位置: 首页 > 后端技术 > Java

面试官:你知道Java中的回调机制吗?我什至无法回答,.

时间:2023-04-01 22:06:18 Java

来源:https://www.cnblogs.com/prayj...在一个应用系统中,不管用什么语言开发,模块之间肯定有调用,调用方式有好几种。1.同步调用同步调用是最基本、最简单的调用方式。A类的方法a()调用B类的方法b(),等待b()方法执行完毕,a()方法继续Go。这种调用方式适用于方法b()执行时间不长的情况,因为如果b()方法执行时间长或者直接阻塞,a()方法剩余的代码就无法执行,这会造成整个进程的Blocking。2.异步调用异步调用是为了解决同步调用可能出现的阻塞,导致整个流程卡住的一种调用方式。A类的方法methoda()通过开启一个新的线程Methodb()来调用B类的方法Methodb(),然后直接执行代码,这样不管methodb()的执行时间多长,执行方法a()不会被阻塞。但是这样一来,由于方法a()不会等待方法b()的执行,当方法a()的执行需要方法b()的执行结果时(根据具体的业务,有些业务比如启动异步线程发送微信通知或者刷新缓存都不是必须的),通过某种方式监听方法b()的执行结果。在Java中,您可以使用Future+Callable来执行此操作。3.回调如下图所示,回调是一种双向调用的方法。其实回调也可以分为同步和异步。解释中是同步回调。第二个例子使用异步回调。callback的思路是:classA类的a()方法调用B类的b()方法,B类的b()方法执行完毕后,主动调用A类的callback()方法.然后B类依次调用A类中的方法D。方法D称为回调方法。说头晕是不是有点头晕?其实一开始我也不懂。方法:A类实现接口CallBack回调——后台1A类包含B类的引用b——后台2B类有一个方法f(CallBackcallback),参数为callback——后台3A对象a调用B的方法f(CallBackcallback)——A类调用B类的某个方法C然后b可以在f(CallBackcallback)方法中调用A的方法——B类调用A类的某个方法D回调类型分为同步回调和异步回调,如果模拟买彩票的场景,我买彩票,调用彩票网,给我返回的结果,判断我是否中奖。同步回调是我买彩票后,需要等彩票网返回给我,结果这个时候不能做其他事情,只能等结果,这个叫synchronouscallback,synchronized,就是等待,我不能做其他的事情,我得等,异步回调是,我买了彩票之后,我可以做其他的事情,然后当彩票网络有结果和消息的时候,它会给我回信息。最明显的方法是在获取彩票结果的函数中添加另一个方法。如果我的其他方法可以立即执行,那么就是异步的(需要很长时间才能判断是否中奖),而在测试函数中,前后两个,发生在测试函数的线程中,一定要有序,在这个地方不是展示同步和异步的地方。同步回调同步回调和异步回调主要体现在是否需要等待。同步调用,如果被调用方的API(第三方API)处理问题的时间比较长,我们需要等待,那就是同步回调,如果调用完了,我们就不需要理解和得到结果。我们调整后离开,去做其他事情。那就是异步调用。异步调用需要在我们调用第三方API的地方开启一个新的线程,而同步调用和普通调用没有区别。推荐一个开源免费的SpringBoot最全教程:https://github.com/javastacks/spring-boot-best-practice实例OrderResult接口,方法getOrderResultpublicinterfaceOrderResult{/***订单商品状态**@paramstate*@return*///参数可以用也可以不用,看你的实际需要。publicStringgetOrderResult(Stringstate);}Store类,store提供了一个不返回预定消息的接口,回调OrderResult接口的方法将订购商品的状态返回给它,重点是returnOrderGoodsInfo(OrderResultorder)方法,它反映了回调的返回。Store是被调用方,被调用方需要回去调用调用方的方法。以上就是回调接口的方法。公共类商店{@Getter@Setter私有字符串名称;Store(Stringname){this.name=name;}/*回调函数,将结构传给我们不能直接调用的方法,然后获取结果*/publicStringreturnOrderGoodsInfo(OrderResultorder){String[]s={"Ordering...","Orderfailed",“即将发货!”,“运输中...”,“;Alreadyindelivery"};Randomrandom=newRandom();inttemp=random.nextInt(5);Strings1=s[temp];returnorder.getOrderResult(s1);}}SyncBuyer类,同步客户类,其中,获取商品的订单状态,orderGoods()调用store的returnOrderGoodsInfo()方法返回商品调用信息,但是在Store类的returnOrderGoodsInfo()方法中,OrderResult接口作为parameter,依次调用OrderResult接口,这是因为调用了它的子类SyncBuyer本身,将其作为参数,调用了getOrderResult(Stringstate)方法,也就是OrderResult接口的方法,相当于完成一个调用周期,然后得到我们自己无法给出的结果这个地方的“循环”是回调的关键。需要调用外部其他方法获取结果的一方,一般会继承一个回调接口,实现它,然后调用第三方的API方法。第三方是在我们调用的方法之间,回调结构作为参数,然后调用接口中的方法,可以返回相应的结果给我们。需要注意的是,虽然我们实现了这个接口的方法,但是在我们自己的类中,或者这个类本身,却无法调用这个方法。也可以说调用这个类的这个方法是不会产生有效结果的。回调的返回体现在这里,在Store类中的returnOrderGoodsInfo(OrderResultorder)方法中,已经很好的体现了。预订状态*/publicclassSyncBuyerimplementsOrderResult{@Getter@SetterprivateStorestore;//Store@Getter@SetterprivateStringbuyerName;//购物者姓名@Getter@SetterprivateStringgoodsName;//购买商品名称SyncBuyer(Storestore,StringbuyerName,StringgoodsName){this.store=商店;this.buyerName=buyerName;this.goodsName=goodsName;}/*调用以从商店返回有关订购商品的信息*/publicStringorderGoods(){StringgoodsState=store.returnOrderGoodsInfo(this);System.out.println(goodsState);myFeeling();//测试是同步还是异步,同步需要等待,异步不需要等待returngoodsState;}publicvoidmyFeeling(){String[]s={"有点小激动","好期待!","希望是个好产品!"};随机random=newRandom();inttemp=random.nextInt(3);System.out.println("我是"+this.getBuyerName()+",我现在的感受:"+s[temp]);}/*回调方法,我们自己不调用,这个方法给出的结果是其他接口或者程序给我们的,我们不能自己生成*/@OverridepublicStringgetOrderResult(Stringstate){return"in"+this.getStore().getName()+"商店已订购"+this.getGoodsName()+"玩具,当前预订状态为:"+state;}}Test2Callback类,测试同步回调结果,publicclassTest2Callback{publicstaticvoidmain(String[]args){StorewallMart=newStore("沙中路沃尔玛");SyncBuyersyncBuyer=newSyncBuyer(wallMart,"小明","铁扇公主");System.out.println(syncBuyer.orderGoods());}}异步回调同步回调和异步回调在代码层面的区别就是我们调用的地方是否为第三方API开辟了一个新的线程,其他的例子没有区别。OrderResult接口示例,方法getOrderResultpublicinterfaceOrderResult{/***order购买商品的状态**@paramstate*@return*///参数可以使用也可以不使用,是否使用可以根据自己的实际需要决定。publicStringgetOrderResult(Stringstate);}Store类,store提供了一个不返回预定消息的接口,回调OrderResult接口的方法返回预约商品的状态。公共类商店{@Getter@Setter私有字符串名称;Store(Stringname){this.name=name;}/*回调函数,传递结构给我们一个不能直接调用的方法,然后获取结果*/publicStringreturnOrderGoodsInfo(OrderResultorder){String[]s={"Ordering...","Orderfailed","即将发货!","运输途中..","已经发货"};随机random=newRandom();inttemp=random.nextInt(5);字符串s1=s[温度];返回订单.getOrderResult(s1);}}NoSyncBuyer类,异步调用Store类的returnOrderGoodsInfo(OrderResultorder)方法返回商品转换结果。/*异步*/@Slf4jpublicclassNoSyncBuyerimplementsOrderResult{@Getter@SetterprivateStorestore;//Store@Getter@SetterprivateStringbuyerName;//购物者姓名@Getter@SetterprivateStringgoodsName;//购买商品名称NoSyncBuyer(Storestore,StringbuyerName,StringgoodsName){this.store=store;this.buyerName=buyerName;this.goodsName=goodsName;}/*调用返回商店订购商品的信息*/publicStringorderGoods(){StringgoodsState="--";MyRunnablemr=newMyRunnable();线程t=新线程(先生);t.开始();System.out.println(goodsState);goodsState=mr.getResult();//获取返回值myFeeling();//用于测试异步是否还在顺序执行returngoodsState;}publicvoidmyFeeling(){String[]s={"有点激动","期待!","希望是个好产品!"};随机random=newRandom();inttemp=random.nextInt(3);System.out.println("我是"+this.getBuyerName()+",我现在的感觉:"+s[temp]);}/*被回调的方法,我们自己不调用,这个方法给出的结果是其他接口或者程序给我们的,我们不能自己生成*/@OverridepublicStringgetOrderResult(Stringstate){返回“输入"+this.getStore().getName()+"已按店铺订购"+this.getGoodsName()+"玩具,当前订单状态为:"+state;}//又启动了一个线程,但是没有返回值,怎么回事//调试的时候,等一会,还是可以拿到值,但是不是马上,打印出来的时候是null,需要付出代价注意力?私有类MyRunnable实现Runnable{@Getter@Setter私有字符串结果;@Overridepublicvoidrun(){try{Thread.sleep(10000);result=store.returnOrderGoodsInfo(NoSyncBuyer.this);//使用匿名函数时,无法返回返回值}catch(InterruptedExceptione){log.error("出错了,异步回调有问题",e);}}}}Test2Callback类,测试同步回调和异步回调的结果。publicclassTest2Callback{publicstaticvoidmain(String[]args){StorewallMart=newStore("沙中路沃尔玛");SyncBuyersyncBuyer=newSyncBuyer(wallMart,"小明","铁扇公主");System.out.println(syncBuyer.orderGoods());系统输出.println("\n");Storelawson=newStore("沙中路罗森便利店");NoSyncBuyernoSyncBuyer=newNoSyncBuyer(lawson,"樱桃","变形金刚");System.out.println(noSyncBuyer.orderGoods());}}近期热点文章推荐:1.1000+Java面试题及答案(2022最新版)2.厉害了!Java协程来了。.3.SpringBoot2.x教程,太全面了!4.不要用爆破爆满画面,试试装饰者模式,这才是优雅的方式!!5.《Java开发手册(嵩山版)》最新发布,赶快下载吧!感觉不错,别忘了点赞+转发!