回调方法Callbak方法的理解——Java中回调的实现方式 从系统调用角度理解回调

在这里插入图片描述

目录

  • 回调方法实现
    • 用反射实现
    • 直接调用callback
      • 进化:接口实现分离
    • 匿名内部类 到 函数式编程
  • 从系统调用角度理解回调
    • 同步调用
    • 异步调用
      • 不需要对方结果
      • 需要对方的结果
  • 菜鸡问大佬问题案例
    • 同步回调
    • 异步回调
    • 基于Future的半同步


回调方法就是一个参数,将一个A方法作为参数传到B方法里面,当B方法执行完之后,再执行传进去的这个A方法,这个过程就叫做回调。

回调方法是类A调用类B的方法,然后B又在某个时候反过来调用类B的方法a,这个a就是回调方法.

回调方法实现

回调方法就是一个参数,将一个A方法作为参数传到B方法里面,当B方法执行完之后,再执行传进去的这个A方法,这个过程就叫做回调。

回调方法是类A调用类B的方法,然后B又在某个时候反过来调用类B的方法a,这个a就是回调方法.

用反射实现

在这里插入图片描述

main方法

package com.tianju.callback;

public class Main {
    public static void main(String[] args) throws Exception{
        Request request = new Request();
        System.out.println("[Main]:我开了一个线程去异步发送请求");

        new Thread(()->{
            try {
                request.send(Callback.class, Callback.class.getMethod("processResponse"));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }).start();

        System.out.println("[Main]:请求发送完毕,do other things");
        Thread.sleep(10000);
    }
}

在这里插入图片描述

package com.tianju.callback;

import java.lang.reflect.Method;

public class Request {
    public void send(Class clazz, Method method) throws Exception{
        // wait for response
        Thread.sleep(3000); // 模拟等待响应
        System.out.println("[Response ]: 收到响应");
        method.invoke(clazz.newInstance());
    }
}

callback

package com.tianju.callback;

public class Callback {

    // callback details
    public void processResponse(){
        System.out.println("[callback]: 处理响应");
    }
}

直接调用callback

在这里插入图片描述

main

package com.tianju.dirctCall;

public class Main {
    public static void main(String[] args) throws Exception{
        Request request = new Request();
        System.out.println("[Main]:我开了一个线程去异步发送请求");

        Callback callback = new Callback();

        new Thread(()->{
            try {
                request.send(callback);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }).start();


        System.out.println("[Main]:请求发送完毕,do other things");
        Thread.sleep(10000);
    }
}

request

package com.tianju.dirctCall;


public class Request {
    public void send(Callback callback) throws Exception{
        // wait for response
        Thread.sleep(3000); // 模拟等待响应
        System.out.println("[Response ]: 收到响应");
        callback.processResponse();
    }
}

进化:接口实现分离

在这里插入图片描述

匿名内部类 到 函数式编程

可以实现匿名内部类

在这里插入图片描述

package com.tianju.lamda;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Request request = new Request();
        System.out.println("[Main]:我开了一个线程去异步发送请求");
        new Thread(()->{
            try {
                request.send(new Callback() {
                    @Override
                    public void processResponse() {
                        System.out.println("[callback]: 处理响应");
                    }
                });
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }).start();
        System.out.println("[Main]:请求发送完毕,do other things");
        Thread.sleep(10000);
    }
}

最终进化的形态,函数式编程

在这里插入图片描述

main

package com.tianju.lamda;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Request request = new Request();
        System.out.println("[Main]:我开了一个线程去异步发送请求");
        new Thread(()->{
            try {
                request.send(()->{
                    System.out.println("[Callback]: 处理响应");
                });
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }).start();
        System.out.println("[Main]:请求发送完毕,do other things");
        Thread.sleep(10000);
    }
}

从系统调用角度理解回调

应用系统模块之间的调用,通常分为:同步调用,异步调用,回调。

同步调用

在这里插入图片描述

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

异步调用

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

异步通常分两种情况:第一,不需要调用结果,直接调用即可,比如发送消息通知;第二,需要异步调用结果,在Java中可使用Future+Callable实现。

不需要对方结果

在这里插入图片描述

需要对方的结果

回调属于一种双向的调用方式。回调的基本上思路是:A调用B,B处理完之后再调用A提供的回调方法(通常为callbakc())通知结果。

在这里插入图片描述

菜鸡问大佬问题案例

同步回调

在这里插入图片描述

package com.tianju.sycCallback;

public interface Callback {
    void callback(String str);
}
package com.tianju.sycCallback;

public class Person implements Callback{

    // @Autowired
    private Genius genius = new Genius();


    @Override
    public void callback(String str) {
        System.out.println("收到了答案:"+str);
    }

    public void ask(){
        System.out.println("菜鸡向大佬请教问题:");
        genius.answer(this);
    }

    public static void main(String[] args) {
        Person person = new Person();
        person.ask();
    }
}

在这里插入图片描述

package com.tianju.sycCallback;

public class Genius {

    public void answer(Callback callback){
        System.out.println("正在忙别的事情。。。。");
        try {
            Thread.sleep(2000);
            System.out.println("忙完了别的事情,开始思考问题。。。。。");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        System.out.println("思考出了问题的答案!结果为:XXXX");
        callback.callback("XXXX");
    }
}

在这里插入图片描述

在这里插入图片描述

异步回调

在这里插入图片描述

在这里插入图片描述

package com.tianju.asyCallback;

public class Person implements Callback {

    // @Autowired
    private Genius genius = new Genius();


    @Override
    public void callback(String str) {
        System.out.println("收到了答案:"+str);
    }

    public void askSyn(){
        System.out.println("菜鸡向大佬请教问题:");
        System.out.println("大佬收知道了。。。。");
        new Thread(()->{
            genius.answer(this);
        }).start();
        System.out.println("菜鸡回到自己的座位");

    }

    public static void main(String[] args) {
        Person person = new Person();
        person.askSyn();
    }
}

基于Future的半同步

在Java使用nio后无法立即拿到真实的数据,而是先得到一个"future",可以理解为邮戳或快递单,为了获悉真正的数据我们需要不停的通过快递单号"future"查询快递是否真正寄到。

Futures是一个抽象的概念,它表示一个值,在某一点会变得可用。一个Future要么获得计算完的结果,要么获得计算失败后的异常。

通常什么时候会用到Future呢?一般来说,当执行一个耗时的任务时,使用Future就可以让线程暂时去处理其他的任务,等长任务执行完毕再返回其结果。

经常会使用到Future的场景有:1. 计算密集场景。2. 处理大数据量。3. 远程方法调用等。

Java在 java.util.concurrent包中附带了Future接口,它使用Executor异步执行。

例如下面的代码,每传递一个Runnable对象到ExecutorService.submit()方法就会得到一个回调的Future,使用它检测是否执行,这种方法可以是同步等待线处理结果完成

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

package com.tianju.future;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class TestFuture {

    public static void main(String[] args) {

        //实现一个Callable接口
        Callable<User> c = () -> {
            //这里是业务逻辑处理
            System.out.println("开始处理业务了");

            //让当前线程阻塞1秒看下效果
            Thread.sleep(2000);
            return new User("张三");
        };

        ExecutorService es = Executors.newFixedThreadPool(2);

        // 记得要用submit,执行Callable对象
        Future<User> future = es.submit(c);
        // 一定要调用这个方法,不然executorService.isTerminated()永远不为true
        // 在此关闭中执行以前提交的任务,但不接受任何新任务。把当前任务执行完
        es.shutdown();
        // 无限循环等待任务处理完毕  如果已经处理完毕 isDone返回true
        while (!future.isDone()) {
            System.out.println("I am try");
            try {
                //处理完毕后返回的结果
                User nt = future.get();
                System.out.println("处理完结果了。。。。");
                System.out.println(nt.name);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    static class User {
        private String name;

        private User(String name) {
            this.name = name;
        }
    }
}

参考文章:https://zhuanlan.zhihu.com/p/349951124

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/155928.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Power Automate-创建自定义连接器

点击左侧导航栏&#xff0c;更多&#xff0c;点击全部发现 点击下方的自定义连接器 点击从空白创建 注意命名要用英文 常规信息中可以上传连接器icon、写一些说明 方案是观察接口地址前面的文本&#xff0c;主机是下方接口地址中蓝色框中的内容 点击下一步&#xff0c;根据API自…

CTF-PWN-堆-【前置知识】

CTF-PWN-堆 堆申请堆块main_areanabrk&sbrk函数mallocfreefree后top chunk 堆 由malloc alloc realloc 函数分配 chunk的前指的是地址低的&#xff0c;chunk的高指的是地址高的 申请堆块 ptmalloc2堆管理器&#xff1a; 通俗的讲就是相当于一个”中间商”&#xff0c;在…

Python编程技巧 – 使用列表(list)

Python编程技巧 – 使用列表(list) Python Programming Skills – Using a List 在Python编程语言中&#xff0c;我们会用到许多列表&#xff08;List&#xff09;。 一门强大的编程语言会包含列表&#xff08;或者数组&#xff09;的数据结构。列表&#xff08;或数组&#…

cpolar+LightPicture,将个人电脑改造成公网图床服务器

文章目录 1.前言2. Lightpicture网站搭建2.1. Lightpicture下载和安装2.2. Lightpicture网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 现在的手机越来越先进&#xff0c;功能也越来越多&#xff0c;而手机…

C++ Qt 学习(九):模型视图代理

1. Qt 模型视图代理 Qt 模型视图代理&#xff0c;也可以称为 MVD 模式 模型(model)、视图(view)、代理(delegate)主要用来显示编辑数据 1.1 模型 模型 (Model) 是视图与原始数据之间的接口 原始数据可以是&#xff1a;数据库的一个数据表、内存中的一个 StringList&#xff…

什么是持续集成的自动化测试?

持续集成的自动化测试 如今互联网软件的开发、测试和发布&#xff0c;已经形成了一套非常标准的流程&#xff0c;最重要的组成部分就是持续集成&#xff08;Continuous integration&#xff0c;简称CI&#xff0c;目前主要的持续集成系统是Jenkins&#xff09;。 那么什么是持…

Python爬虫教程:从入门到实战

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;我是涛哥&#xff0c;今天为大家分享 Python爬虫教程&#xff1a;从入门到实战&#xff0c;文章3800字&#xff0c;阅读大约15分钟&#xff0c;大家enjoy~~ 网络上的信息浩如烟海&#xff0c;而爬虫&#xff08;…

4G工业路由器智慧电梯联网应用方案

随着电梯老旧增多及日常管理上缺失&#xff0c;电梯安全运行上存在一定的问题&#xff0c;从全国电梯统计数据中可以发现&#xff0c;主要的电梯困人、故障事件发生在住宅小区&#xff0c;当前&#xff0c;住宅小区的电梯绝大多数是通过物业公司负责管理&#xff0c;物业公司安…

【尘缘赠书活动第四期】推荐几本架构师成长和软件架构技术相关的好书,助你度过这个不太景气的寒冬!

目录 1 《高并发架构实战&#xff1a;从需求分析到系统设计》2《架构师的自我修炼&#xff1a;技术、架构和未来》3《中台架构与实现&#xff1a;基于DDD和微服务》4《分布式系统架构&#xff1a;架构策略与难题求解》5《流程自动化实战&#xff1a;系统架构和软件开发视角 》6…

验证码识别之OCR识别

验证码识别&#xff1a; 背景&#xff1a; ​ 决定开一个专题给大家讲一下验证码识别&#xff0c;不要多想&#xff0c;我们不搞深度学习&#xff0c;知识用于攻破模拟登录的时候弹出的验证码&#xff0c;后续会给大家讲讲滑块等等&#xff0c;反爬虫策略如何应对。 好了&am…

大会技术“硬核”资讯来啦!点击预约 IoTDB 现场一对一调优咨询服务

承诺大家的&#xff0c;2023 IoTDB 用户大会现场“快讯”第一弹来啦&#xff01; 我们将在大会现场设置 IoTDB Workshop&#xff0c;IoTDB 原厂团队将免费提供一对一技术咨询、使用调优、疑问解答等服务。 现场提供的一对一咨询、调优时长为 30 分钟&#xff0c;在您预约的时间…

Linux_VMware 软件安装与虚拟机

从这里开始&#xff0c;我们就踏上了学习 Linux 的路程。长路漫漫亦灿灿&#xff0c;祝我也祝所有看到这篇文章的朋友&#xff01;&#xff01;&#xff01; 参考书目&#xff1a;【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.81 / ARM 裸机与嵌入式 Linux 驱动…

Stable Diffusion1.5网络结构-超详细原创

目录 1 Unet 1.1详细整体结构 1.2 缩小版整体结构 1.3 时间步编码 1.4 CrossAttnDownBlock2D 1.4.1 ResnetBlock2D 1.4.2 Transformer2DModel 1.4.2.1 BasicTransformerBlock 1.4.2.1.1 SelfAttention 1.4.2.1.2 CrossAttention 2 VAE 3 CLIP 绘制软件&#xff1a;…

Linux操作系统基础 – 正则表达式快速入门

Linux操作系统基础 – 正则表达式快速入门 Linux Operating System Essentials - Introduction to Regular Expressions 通常在计算机科学领域&#xff0c;正则表达式被解释为对字符串操作的一种逻辑公式&#xff0c;即用事先定义好的特定字符及其组合组成所谓的“规则字符串”…

深度学习之基于YoloV5血红细胞检测识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 深度学习已经在许多领域中得到了广泛的应用&#xff0c;包括医疗健康领域。其中&#xff0c;YOLO&#xff08;You O…

UE基础篇四:地形基础概念

导语: 视频文档在文末 一、从引擎中导入高度图 高度图是灰度图,并且每个像素有16位的深度,支持这种格式的是.png 和.raw格式 高度图可以自己绘制,或者通过许多网站下载那些复制现实世界地点的图片,许多网站也有免费资源下载 二、草地和石头混合图层 创建一个混合材质,…

龙迅LT8912B 单通道MIPIDSI桥接LVDS+HDMI(1.4)同显点屏LVDS,加环出一路HDMI

龙迅LT8912B 描述: Lontium LT8912B MIPIDSI到LVDS和HDMI桥采用单通道MIPID-PHY接收器前端配置&#xff0c;每个通道有4个数据通道&#xff0c;每个数据通道运行1.5Gbps&#xff0c;最大输入带宽可达6Gbps。对于屏幕应用&#xff0c;该桥解码MIPIDSI 18bpp RGB666和24bpp RGB…

系列四、JVM的内存结构【本地接口(Native Interface)】

一、组成 本地接口由本地方法栈&#xff08;Native Method Stack&#xff09;、本地方法接口&#xff08;Native Interface&#xff09;、本地方法库组成。 二、本地接口的作用 本地接口的作用是融合不同的编程语言为Java所用&#xff0c;它的初衷是融合C/C程序&#xff0c;Jav…

【ARM Trace32(劳特巴赫) 使用介绍 5 -- Trace32 scan dump 详细介绍】

文章目录 1.1 JTAG 测试逻辑架构1.2 D型扫描触发器1.2.1 全扫描介绍1.3 IR 寄存器1.4 TDR(Test data registers)1.4.1 TDR 的实现1.4.1.1 Bypass Register1.4.1.2 Boundary-scan register1.5 Scan Dump1.5.1 soft fusion1.1 JTAG 测试逻辑架构 图 1-1 片上测试逻辑概念图 如前面…

YOLOv8-Seg改进:检测头全新创新篇 | S_improve_Segment结构创新

🚀🚀🚀本文改进:S_improve_Segment全新的分割结构头创新,适配各个YOLO 🚀🚀🚀 S_improve_Segment在各个场景都能够有效涨点 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1)手把手教你…