【Java】回调机制、同步/异步调用

一、同步调用

同步调用是最基本的调用方式。类A的a()方法调用类B的b()方法,类A的方法需要等到B类的方法执行完成才会继续执行。如果B的方法长时间阻塞,就会导致A类方法无法正常执行下去。

image-20230731173655301

二、异步调用

如果A调用B,B的执行时间比较长,那么就需要考虑进行异步处理,使得B的执行不影响A。通常在A中新起一个线程用来调用B,然后A中的代码继续执行。

异步通常分两种情况:

  • 第一,不需要调用结果,直接调用即可,比如发送通知;
  • 第二,需要异步调用结果,在Java中可使用Future+Callable实现。

image-20230731173939792

三、回调

image-20230731183014782

通常回调分为:同步回调和异步回调。

其中同步回调与同步调用类似,代码运行到某一个位置的时候,如果遇到了需要回调的代码,会在这里等待,等待回调结果返回后再继续执行。

异步回调与异步调用类似,代码执行到需要回调的代码的时候,并不会停下来,而是继续执行,当然可能过一会回调的结果会返回回来。

1、同步回调

image-20230731183054743

制作Callback接口

public interface Callback {
    void CallbackData(String Data);
}

自定义向小明提问的人:

public class CallbackHanler implements Callback{

    Caller caller;


    public CallbackHanler(Caller caller) {
        this.caller = caller;
    }

    @Override
    public void CallbackData(String Data) {
        Log.d("TAG!","你懂了,答案为"+Data);
    }

    public void ask(){
        caller.DoWork(this);
    }
}

大佬小明:

public class Caller {
    public void DoWork(Callback callback){
        Log.d("TAG!","小明进行自己的工作");
        try {
            Thread.sleep(5000);
            Log.d("TAG!","开始解决你的问题");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        Log.d("TAG!","问题答案为2");
        //传递问题答案
        callback.CallbackData("2");
    }
}

在Main函数中调用这两个类:

Caller caller = new Caller();
CallbackHanler callbackHanler = new CallbackHanler(caller);
callbackHanler.ask();
Log.d("TAG!","你在等待。。。。");

打印结果如下:

image-20230731210038657

上面的实例演示了同步回调,很明显在调用的过受到Caller执行时长的影响,需要等到Caller处理完才能继续执行CallbackHanler方法中的后续代码。

2、异步回调

修改CallbackHanler的ask()方法如下:

    public void ask(){
        new Thread(()-> caller.DoWork(this)).start();
    }

打印结果如下:

image-20230731210207211

通过Main函数的Log.d(“TAG!”,“你在等待。。。。”);可以知道,此时main函数没有等待ask(),而是直接继续执行。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
当涉及到网络请求时,同步调用和异步调用可以用以下示例来说明: 1. 同步调用示例: 假设我们需要通过网络请求获取某个网站的数据,并将其打印出来。在同步调用中,代码会在发送请求后等待响应返回后再继续执行。 ```java import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; public class SyncExample { public static void main(String[] args) { try { // 创建URL对象 URL url = new URL("https://example.com"); // 打开连接并获取输入流 BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); // 读取数据并打印 String line; while ((line = reader.readLine()) != null) { System.out.println(line); } // 关闭连接 reader.close(); } catch (IOException e) { e.printStackTrace(); } // 其他代码... } } ``` 在这个示例中,`url.openStream()` 是一个同步调用,它会阻塞代码的执行直到数据完全加载并返回。 2. 异步调用示例: 现在我们使用异步调用来实现相同的功能。在异步调用中,代码会在发送请求后继续执行,不会等待响应的返回。 ```java import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.util.concurrent.CompletableFuture; public class AsyncExample { public static void main(String[] args) { // 创建URL对象 URL url; try { url = new URL("https://example.com"); // 使用CompletableFuture来进行异步请求 CompletableFuture.supplyAsync(() -> { try { // 打开连接并获取输入流 BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); // 读取数据并返回 StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } // 关闭连接 reader.close(); return response.toString(); } catch (IOException e) { e.printStackTrace(); } return null; }).thenAccept(response -> { // 异步操作完成后执行的回调,打印响应结果 System.out.println(response); }); } catch (IOException e) { e.printStackTrace(); } // 其他代码... } } ``` 在这个示例中,我们使用了`CompletableFuture`来进行异步请求。`url.openStream()` 被包装在一个异步任务中,当任务完成后会调用 `thenAccept` 方法指定的回调函数来处理响应结果。这样,在请求发送后,代码会立即继续执行,不会等待响应返回。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摸鱼小小虫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值