首页 > 技术文章 > 详解java 三种调用机制(同步、回调、异步)

haoran8222 2021-08-20 15:24 原文

同步调用、回调和异步调用。

同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;

 

回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;

具体说来:就是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。

仅仅用来学习,如有侵权,联系我,马上删除。

推荐阅读