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

news2024/11/28 20:45:14

在这里插入图片描述

目录

  • 回调方法实现
    • 用反射实现
    • 直接调用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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

filter - 常用滤镜效果(毛玻璃、图片阴影、图片褪色)

文章目录 filter 属性滤镜算法函数blur&#xff1a;高斯模糊hue-rotate&#xff1a;色相环contrast&#xff1a;对比度grayscale&#xff1a;灰度drop-shadow&#xff1a;图片阴影 常见的滤镜效果图片内容轮廓阴影毛玻璃图片黑白调整图片色相和对比度使元素或文字变圆润 filter…

linux实现SSH免密登录设置,以及shell脚本实现

原创/朱季谦 最近在搭建linux集群&#xff0c;做了SSH免密登录的设置&#xff0c;正好把过程记录一下&#xff1a; 一.用搭建好的两台虚拟机做演示&#xff0c;A机器&#xff1a;192.168.200.129&#xff0c;B机器&#xff1a;192.168.200.128 二.分别在两台机器上执行以下步…

Excel Unix时间戳和日期时间格式的相互转换

时间戳转日期时间 ((A18*3600)/86400)DATE(1970,1,1) # 或 (A18*3600)/8640070*36519# 带格式化 TEXT((C18*3600)/8640070*36519,"yyyy-mm-dd hh:mm:ss")首先加8小时进行时区转换&#xff0c;然后转换成天数&#xff0c;再加上1970年1月1日&#xff0c;最后设置日期…

类和对象(7):初始化列表

class Date { public:Date(int year 1, int month 1, int day 1){_year year;_month month;_day day;}private:int _year;int _month;int _day; };构造函数体内的语句只能称为赋初值&#xff0c;不能称为初始化。初始化只能初始化一次&#xff0c;而构造函数体内可以多次…

面向企业的人脸属性检测技术方案

人脸识别技术已经成为企业提升服务质量、优化用户体验的重要工具。美摄科技&#xff0c;作为领先的人工智能技术提供商&#xff0c;我们致力于为企业提供最先进、最全面的人脸属性检测技术解决方案。 我们的AI人脸检测与属性分析技术&#xff0c;能够快速准确地检测人脸并返回…

Python基础:正则表达式(regular expression)详解

在Python中&#xff0c;正则表达式是一种强大的工具&#xff0c;可用于匹配和操作字符串。什么是正则表达式&#xff1f; 正则表达式是一种模式匹配语言&#xff0c;用于匹配字符串中的特定模式。这些模式可以是字母、数字、字符组合或其他符号。正则表达式通常用于文本处理、网…

机器人制作开源方案 | 守护一体化护耆卫士

作者&#xff1a;白玲玲、张硕、孔亚轩单位&#xff1a;兰州理工大学指导老师&#xff1a;毕广利 1. 场景调研 “探索者”平台是结合机械、电子、传感器、计算机软硬件、控制、人工智能和造型技术等众多的先进技术研发推出的专业型机器人设备原型设计工具&#xff0c;包含机构…

【EI会议征稿】第三届图像,信号处理与模式识别国际学术会议(ISPP 2024)

第三届图像&#xff0c;信号处理与模式识别国际学术会议&#xff08;ISPP 2024) 2024 3rd International Conference on Image, Signal Processing and Pattern Recognition&#xff08;ISPP 2024&#xff09; 第三届图像&#xff0c;信号处理与模式识别国际学术会议&#xf…

Android---网络编程优化

网络请求操作是一个 App 的重要组成部分&#xff0c;程序大多数问题都是和网络请求有关。使用 OkHttp 框架后&#xff0c;可以通过 EventListener 来查看一次网络请求的详细情况。一次完整的网络请求会包含以下几个步骤。 也就是说&#xff0c;一次网络请求的操作是从 DNS 解析…

在node-red 的function中使用第三方的npm 库来处理业务逻辑

首先找到node-red的安装目录,这个目录可以在启动日志里看到。 如我的 我的就是在 /Users/fizz/.node-red 进入该目录,安装所需要的库 如 npm install lodash 然后在setting.js 中配置functionGlobalContext // The following property can be used to seed Global Context …

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

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

微服务架构之路7,Nacos配置中心的Pull原理,附源码

目录 一、本地配置二、配置中心1、以Nacos为例&#xff1a;2、Pull模式3、也可以通过Nacos实现注册中心 三、配置中心提供了哪些功能四、如何操作配置中心1、配置注册2、配置反注册3、配置查看4、配置变更订阅 五、主流的微服务注册中心有哪些&#xff0c;如何选择&#xff1f;…

C++核心编程 day09 类型转换、异常、输入输出流

C核心编程 day09 类型转换、异常、输入输出流 1. 类型转换2. 异常2.1 异常语法2.2 C标准异常库 3. 输入输出流3.1 输入输出流概念以及流类库3.2 标准输入流3.3 标准输出流3.4 文件读写 1. 类型转换 C中的类型转换有四类&#xff0c;分别是静态转换、动态转换、常量转换、重新解…

Meta降本增效大招之:弃用产品

今晚无意间进入去哪儿技术沙龙的直播间&#xff0c;听到他们要删除50%的代码和停掉50%的服务。我就想起Meta公司最近写的这篇博客&#xff1a;Automating product deprecation。 这篇博客对于效能平台的建设非常具有指导意义。文章最后有原文链接和我个人的总结。 这是一个系列…

51单片机的基础知识汇总

文章目录 51单片机之点灯51单片机之灯的亮灭交替51单片机之灯的流水灯51单片机之数码管数字显示51单片机之数码管数字的流水灯51单片机之数码管数字的0-7显示51单片机之蜂鸣器的鸣叫与关闭51单片机之DS1302时钟设置51单片机之读出温度传感器温度代码模块化汇总主函数main.c 延时…

XD6500S— LoRa SIP模块

XD6500S是一系列LoRa SIP模块&#xff0c;集成了射频前端和LoRa射频收发器SX1262系列&#xff0c;支持LoRa和FSK调制。收发器SX1262系列&#xff0c;支持LoRa和FSK调制。LoRa技术是一种扩频协议&#xff0c;针对LPWAN 应用的低数据速率、超远距离和超低功耗通信进行了优化。通信…

【Mysql】Mysql内置函数介绍

&#x1f308;欢迎来到Python专栏 &#x1f64b;&#x1f3fe;‍♀️作者介绍&#xff1a;前PLA队员 目前是一名普通本科大三的软件工程专业学生 &#x1f30f;IP坐标&#xff1a;湖北武汉 &#x1f349; 目前技术栈&#xff1a;C/C、Linux系统编程、计算机网络、数据结构、Mys…

Jupyter Notebook的下载安装与使用教程_Python数据分析与可视化

Jupyter Notebook的下载安装与使用 Jupyter简介下载与安装启动与创建NotebookJupyter基本操作 在计算机编程领域&#xff0c;有一个很强大的工具叫做Jupyter。它不仅是一个集成的开发环境&#xff0c;还是一个交互式文档平台。对于初学者来说&#xff0c;Jupyter提供了友好的界…

阿里云ESSD云盘、高效云盘和SSD云盘介绍和IOPS性能参数表

阿里云服务器系统盘或数据盘支持多种云盘类型&#xff0c;如高效云盘、ESSD Entry云盘、SSD云盘、ESSD云盘、ESSD PL-X云盘及ESSD AutoPL云盘等&#xff0c;阿里云服务器网aliyunfuwuqi.com详细介绍不同云盘说明及单盘容量、最大/最小IOPS、最大/最小吞吐量、单路随机写平均时延…

LayoutLMv3 : 基于统一文本和带Masking图像的文档AI预训练【论文翻译】

文章目录 专业名词统计文档智能多模态预训练模型LayoutLMv3&#xff1a;兼具通用性与优越性LayoutLMv3 &#xff1a; 基于统一文本和带Masking图像的文档AI预训练ABSTRACT1 INTRODUCTION2 LAYOUTLMV32.1 Model Architecture&#xff08;模型架构&#xff09;2.2 Pre-training O…