Java中使用回调函数的方法实例

 更新时间:2023年05月29日 15:01:00   作者:BillDavidup  
本文主要介绍了Java中使用回调函数的方法实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

背景

在Java中一个回调的操作是一个在一些操作完成之后被传递到另一个函数中并且被执行的函数。一个回调函数既可以被同步或者异步执行。在一个同步回调函数的案例中,一个函数紧着着另一个函数完成后被执行。在一个异步回调函数的案例中,一个函数不需要在其他函数执行的过程中按照特定顺序时间内被执行。

从在经典的监视者设计模式中使用的监听案例开始,这篇文章向你介绍了Java中的回调函数。你将会看到大量的同步和异步的回调实现,包含使用 CompletableFuture类的函数式回调。

Java中的同步回调

一个同步回调函数总是会在一些操作执行后立刻被执行。这意味着它将会在动作被执行后执行。

正如我提到的,在一个监视者设计模式中使用的一个回调函数的案例。在页面UI的按钮中,需要一个按钮被点击后去实例化一个操作,我们可以传递回调函数作为这个按钮动作的监听器。这个监听函数会一直等待按钮被点击,直到按钮被触发后执行。

现在让我们看代码中一个新的回调概念的案例

匿名内部类中的回调

任何时间我们在Java中,传递一个实现了接口的方法到另一个方法中,我们就是使用了回调函数的概念。在下面的代码中,我们传递了一个Consumer函数接口和一个匿名内部类去实现accept()方法。

一旦 accept() 方法被实现,我们将会在performAction方法里面执行它;然后我们会在Consumer接口里面执行accept() 方法。

import java.util.function.Consumer;
public class AnonymousClassCallback {
  public static void main(String[] args) {
    performAction(new Consumer<String>() {
      @Override
      public void accept(String s) {
        System.out.println(s);
      }
    });
  }
  public static void performAction(Consumer<String> consumer) {
    System.out.println("Action is being performed...");
    consumer.accept("Callback is executed");
  }
}

该代码的输出语句是:

Action is being performed…
Callback is executed…

在以上代码中,我们将Consumer接口传递到performAction() 方法中,然后performAction()方法执行后,调用accept()方法。

你可能注意到,使用一个匿名内部类是相当的啰嗦。使用lambda表达式替代匿名内部类将会更简单。让我们看看当我们在回调函数中使用lambda表达式会发生什么。

lambda的回调

在Java中,我们可以传递使用了lambda表达式实现的函数式接口到一个方法中,然后在一个操作结束后被执行。在代码中看起开是那样。

public class LambdaCallback {
  public static void main(String[] args) {
    performAction(() -> System.out.println("Callback function executed..."));
  }
  public static void performAction(Runnable runnable) {
    System.out.println("Action is being performed...");
    runnable.run();
  }
}

输出结果表明,一旦这个操作执行后,回调即被调用。

在这个例子中,你可能注意到我们在performAction方法中传递了可运行的函数式接口。因此,我们可以重写run()方法并在performAction方法结束后执行run()方法。

异步回调函数

我们经常想去使用一个异步回调方法,这意味着一个方法将会在操作执行时被其他进程异步地调用。当一个回调方法不需要被其他进程立刻调用的时候,它可能对性能有所帮助。

简单线程回调

让我们以最简单的异步回调操作方式开始。在下面的代码中,首先我们从一个可执行的函数式接口中实现了run()方法。然后我们在一个创建线程中使用了它。最终,我们将会启动这个线程去异步地执行这个已实现的可执行函数式接口:

public class AsynchronousCallback {
  public static void main(String[] args) {
    Runnable runnable = () -> System.out.println("Callback executed...");
    AsynchronousCallback asynchronousCallback = new AsynchronousCallback();
    asynchronousCallback.performAsynchronousAction(runnable);
  }
  public void performAsynchronousAction(Runnable runnable) {
    new Thread(() -> {
      System.out.println("Processing Asynchronous Task...");
      runnable.run();
    }).start();
  }
}

这个案例的输出结果是:

Processing Asynchronous Task…
Callback executed…

从上面的代码中,我们创建了一个实现run()方法的Runnable,然后我们调用performAsynchronousAction()方法,传递了Runnable,在新建的线程中run()方法调用了它。

在performAsynchronousAction() 方法内,我们向它传递了一个runnable参数,在方法内部用lambda实现了一个线程的run方法调用了它.。先打印 “Processing Asynchronous Task…” 最终方法内部调用了以参数传进来的runnable方法,打印 “Callback executed…”

平行执行的异步回调

比起在异步调用中回调函数,我们也可以从其他函数中平行地调用一个回调函数。这意味着我们可以开启两个线程,平行地调用这两个函数。

以下代码和之前的有点像,但是要注意到除了直接调用回调函数外,我们可以开启一个新的线程调用回调函数:

// Omitted code from above…
public void performAsynchronousAction(Runnable runnable) {
    new Thread(() -> {
      System.out.println("Processing Asynchronous Task...");
      new Thread(runnable).start();
    }).start();
  }

输出结果是:

Processing Asynchronous Task…
Callback executed…

当我们不需要回调函数在performAsynchronousAction() 方法调用之后被立刻执行,异步平行调用回调函数是非常有用的。

一个真实世界的案例,当我们在线上购买一个产品,我们不需要等待付款被确认后才执行检查库存等所有的这些重度操作。在这个案例中,回调在后台执行的同时我们可以做其他事情。

CompletableFuture中的回调

使用异步回调函数的另一种方法是使用CompletableFuture API。Java8中引入的这个强大的API有助于执行和组合异步方法调用。它完成了我们在上一个示例中所做的一切,例如创建一个新的线程,然后启动和管理它。

在下面的代码示例中,我们将创建一个新的CompletableFuture,然后调用传递String的supplyAsync方法。

接下来,我们将创建另一个CompletableFuture,它将应用回调函数来执行我们配置的第一个函数:

import java.util.concurrent.CompletableFuture;
public class CompletableFutureCallback {
  public static void main(String[] args) throws Exception {
    CompletableFuture<String> completableFuture
        = CompletableFuture.supplyAsync(() -> "Supply Async...");
    CompletableFuture<String> execution = completableFuture
        .thenApply(s -> s + " Callback executed...");
    System.out.println(execution.get());
  }
}

它的输出结果如下:

Supply Async… Callback executed…

结论

回调在软件开发中到处使用,广泛地使用在工具、设计模式和应用程序中。有时候我们使用它们的时候却没有注意到。

在java代码中,我们通过大量常见的回调实现帮助我们解释它们广泛的用处。这里有一些回调的特征需要我们记住:

  • 回调函数应该在执行另一个操作时执行,或者与该操作并行执行。
  • 回调函数可以被同步执行,意味着它可以在其他操作执行后没有延迟地被立刻执行。
  • 回调函数可以是异步的,这意味着它可以在后台执行,并且可能需要一些时间才能执行
  • Observable设计模式使用回调来通知感兴趣的实体何时发生了操作。

到此这篇关于Java中使用回调函数的方法实例的文章就介绍到这了,更多相关Java 回调函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Cloud 中自定义外部化扩展机制原理及实战记录

    Spring Cloud 中自定义外部化扩展机制原理及实战记录

    这篇文章主要介绍了Spring Cloud 中自定义外部化扩展机制原理及实战,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • Spring中IoC优点与缺点解析

    Spring中IoC优点与缺点解析

    这篇文章主要为大家详细解析了Spring中IoC优点与缺点,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • java判断字符串包含某个字符的实例方法

    java判断字符串包含某个字符的实例方法

    在本篇文章里小编给大家整理的是一篇关于java判断字符串包含某个字符的实例方法,有需要的朋友们学习下。
    2019-12-12
  • SpringMvc请求处理参数 和 响应数据处理的示例详解

    SpringMvc请求处理参数 和 响应数据处理的示例详解

    这篇文章主要介绍了SpringMvc请求处理参数和响应数据处理,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • Java判断对象是否为空(包括null ,

    Java判断对象是否为空(包括null ,"")的方法

    这篇文章主要介绍了Java判断对象是否为空(包括null ,"")的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • Mybatis分页插件PageHelper的配置和简单使用方法(推荐)

    Mybatis分页插件PageHelper的配置和简单使用方法(推荐)

    在使用Java Spring开发的时候,Mybatis算是对数据库操作的利器了。这篇文章主要介绍了Mybatis分页插件PageHelper的配置和使用方法,需要的朋友可以参考下
    2017-12-12
  • IntelliJ IDEA配置Tomcat(完整版图文教程)

    IntelliJ IDEA配置Tomcat(完整版图文教程)

    这篇文章主要介绍了IntelliJ IDEA配置Tomcat(完整版图文教程),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • springboot+vue实现七牛云头像的上传

    springboot+vue实现七牛云头像的上传

    本文将介绍如何在Spring Boot项目中利用七牛云进行图片上传并将图片存储在云存储中,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-08-08
  • win10 下 idea2020安装 JetBrains-agent.jar 包后闪退的问题及解决办法

    win10 下 idea2020安装 JetBrains-agent.jar 包后闪退的问题及解决办法

    这篇文章主要介绍了win10 下 idea2020安装 JetBrains-agent.jar 包后闪退的解决办法,本文给大家带来原因分析及解决方法,需要的朋友可以参考下
    2020-08-08
  • Java详细讲解IO流的Writer与Reader操作

    Java详细讲解IO流的Writer与Reader操作

    Writer与Reader类不能直接调用,需要使用多带的方法调用它们的子类,在他们的前边加上一个File即可如(FileWriter或FileReader)的多态方法进行其调用,并且他们也是抽象类调用需要连接接口Exception,它们的优点在于可以直接写入或读出内容,不需要使用byte转八进制
    2022-05-05

最新评论