详解java 三种调用机制(同步、回调、异步)
同步调用、回调和异步调用。
同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;
回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;
具体说来:就是A类中调用B类中的某个方法C,然后B类中反过来调用A类中的方法D,D这个方法就叫回调方法,
异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。
多线程是异步处理,异步就意味着不知道处理结果。回调一般是异步处理的一种技术。
Future 半异步, 线程+callback 全异步, java8 CompletableFurute 异步回调链式编排。
同步回调
下面的例子去掉开启多线程就是同步回调。
异步回调的使用
1、定义接口
public interface CallBack { public void solve(String result); }
2、主调程序
public class CallbackRequest implements Callback{ private CallbackResponse callbackResponse; public CallbackRequest(CallbackResponse callbackResponse) { this.callbackResponse = callbackResponse; } //主调需要解决一个问题,所以他把问题交给被调处理,被调单独创建一个线程,不影响主调程序的运行 public void request(final String question){ System.out.println("主调程序问了一个问题"); new Thread(()->{ //B想要帮A处理东西,就必须知道谁让自己处理的,所以要传入a,也要知道a想处理什么,所以要传入question callbackResponse.handler(this, question); }).start(); //A把要处理的事情交给b之后,就可以自己去玩耍了,或者去处理其他事情 afterAsk(); } private void afterAsk(){ System.out.println("主调程序继续处理其他事情"); } @Override public void solve(String result) { System.out.println("被调程序接到答案后进行处理" + result); } }
3、被调程序:
public class CallbackResponse { public void handler(Callback callback, String request) { System.out.println(callback.getClass()+"问的问题是:"+ request); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } String result="\n答案是2"; callback.solve(result); } }
4、测试:
public class CallbackTest { public static void main(String[] args) { CallbackResponse callbackResponse = new CallbackResponse(); CallbackRequest callbackRequest = new CallbackRequest(callbackResponse); callbackRequest.request("1+1"); } } 输出: 主调程序问了一个问题 主调程序继续处理其他事情 class javapratice.CallbackRequest问的问题是:1+1 被调程序接到答案后进行处理 答案是2
一句话解释回调:当前方法有一段逻辑,需要调用者来决定怎么执行。这段逻辑肯定不能写死,所以需要一个接口,来解耦当前方法和调用者!
Java多线程中可以通过callable和future或futuretask结合来获取线程执行后的返回值。实现方法是通过get方法来调用callable的call方法获取返回值。
其实这种方法本质上不是回调,回调要求的是任务完成以后被调用者主动回调调用者的接口,而这里是调用者主动使用get方法阻塞获取返回值。
Callable的使用
1、结合Callable和Future一起使用,通过ExecutorService的submit方法执行Callable,并返回Future。
ExecutorService executor = Executors.newCachedThreadPool();
Future<String> future = executor.submit(() ->
{ System.out.println("call"); TimeUnit.SECONDS.sleep(1); return "str"; } );
//手动阻塞调用get通过call方法获得返回值。 System.out.println(future.get()); //需要手动关闭,不然线程池的线程会继续执行。 executor.shutdown();
2、使用futuretask同时作为线程执行单元和数据请求单元
FutureTask<Integer> futureTask = new FutureTask(() ->
{ System.out.println("dasds"); return new Random().nextInt(); });
new Thread(futureTask).start(); //阻塞获取返回值 System.out.println(futureTask.get());
注:比起future.get(),其实更推荐使用get (long timeout, TimeUnit unit)方法,设置了超时时间可以防止程序无限制的等待future的结果。
文章来自:https://www.cnblogs.com/liujiarui/p/13395424.html。
仅仅用来学习,如有侵权,联系我,马上删除。