Java中的异步回调问题

 更新时间:2023年12月20日 08:44:07   作者:bat在等我  
这篇文章主要介绍了Java中的异步回调问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

有时候我们执行一个任务需要很长时间,单线程环境下 会处于阻塞状态,严重影响效率,那么可以使用一种非阻塞的处理方式,这就是使用多线程。

多线程情况下,问题出来了,我们不知道线程什么时候执行完毕,或者不知道如何处理子线程的结果

那么就有以下两种方式:异步回调同步等待线程处理结果两种方式

1. 异步回调

直接上代码,固定格式:主业务代码和一个处理结果的接口

/**
 * Callback
 * 回调一般是异步处理的一种技术。
 * 一个回调是被传递到并且执行完该方法。 这种方式只能异步回调,
 * 如果需要同步等待线程处理结果可以使用下面介绍的Futures
 */
interface MyCallback {

    void doCallback(Map<String, Object> params);
}

public class TestAsyncCallBack {

    static ExecutorService es = Executors.newFixedThreadPool(2);

    public static void doSomething(MyCallback callback) {
        // 初始化一个线程  
        Thread t = new Thread() {
            public void run() {

                // 这里是业务逻辑处理  
                System.out.println("子线任务开始执行:" + Thread.currentThread().getId());
                // 为了能看出效果 ,让当前线程阻塞5秒  
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("子线任务结束执行:");
                // 处理完业务逻辑,  
                Map<String, Object> params = new HashMap<String, Object>();
                params.put("a1", "子线程处理结果");
                callback.doCallback(params);
            }
        };
        es.execute(t);
        //一定要调用这个方法,不然executorService.isTerminated()永远不为true
        es.shutdown();
    }

    public static void main(String[] args) {
        // 内部类 等价于 new MyCallBack(){...}, 主要作用就是重写doCallback方法
        doSomething((params) -> {
            System.out.println("单个线程也已经处理完毕了,返回参数a1=" + params.get("a1"));
        });

        System.out.println("主线任务已经执行完了:" + Thread.currentThread().getId());
    }
}

2. 使用Future同步等待执行结果

主要是利用了Callable接口开启进行多线程,call方法可以返回结果

/**
 * Futures是一个抽象的概念,它表示一个值,该值可能在某一点变得可用。一个Future要么获得计算完的结果,要么获得计算失败后的异常
 * 每传递一个Runnable对象到ExecutorService.submit()方法就会得到一个回调的Future,你能使用它检测是否执行,这种方法可以是同步等待线处理结果
 */
public class TestFuture {
    public static void main(String[] args) {
        Callable<Result> callable = new Callable<Result>() {
            @Override
            public Result call() throws Exception {
                //这里是业务逻辑处理
                //让当前线程阻塞1秒看下效果
                Thread.sleep(5000);
                return new Result("张三");
            }
        };
        ExecutorService executorService = Executors.newFixedThreadPool(5);

        Future<Result> resultFuture = executorService.submit(callable);
        executorService.shutdown();

        /**
         * 无限循环等待任务处理完毕  如果已经处理完毕 isDone返回true
         */
        while (!resultFuture.isDone()) {
            try {
                Result result = resultFuture.get(); // 在这一步阻塞知直到得到子线程返回结果
                System.out.println(result.getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
}

class Result {

    private String name;

    public Result(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot整合Swagger的方法示例

    SpringBoot整合Swagger的方法示例

    这篇文章主要介绍了SpringBoot整合Swagger的方法示例,详细介绍了SpringBoot如何整合Swagger以及swagger注解,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • SpringBoot依赖及其作用分析

    SpringBoot依赖及其作用分析

    这篇文章主要介绍了SpringBoot依赖及其作用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • mybatis的使用-Mapper文件各种语法介绍

    mybatis的使用-Mapper文件各种语法介绍

    这篇文章主要介绍了mybatis的使用-Mapper文件各种语法介绍,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • Java8之lambda表达式基本语法

    Java8之lambda表达式基本语法

    本文通过示例大家给大家介绍了java8之lambda表达式的基本语法,感兴趣的的朋友一起看看吧
    2017-08-08
  • IDEA快速搭建spring boot项目教程(Spring initializr)

    IDEA快速搭建spring boot项目教程(Spring initializr)

    这篇文章主要介绍了IDEA快速搭建spring boot项目教程(Spring initializr),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • SpringBoot实现在一个模块中引入另一个模块

    SpringBoot实现在一个模块中引入另一个模块

    这篇文章主要介绍了SpringBoot实现在一个模块中引入另一个模块的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • MyBatis中如何查询某个时间段内的数据

    MyBatis中如何查询某个时间段内的数据

    这篇文章主要介绍了MyBatis中如何查询某个时间段内的数据,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Windows编写jar启动脚本和关闭脚本的操作方法

    Windows编写jar启动脚本和关闭脚本的操作方法

    脚本文件,通常放入/bin目录下,编写启动脚本需要保证能够识别到对应的jar文件,其次需要保证能够识别到/config中的配置文件信息,这篇文章主要介绍了Windows编写jar启动脚本和关闭脚本的操作方法,需要的朋友可以参考下
    2022-12-12
  • springboot集成Swagger的方法(让你拥有属于自己的api管理器)

    springboot集成Swagger的方法(让你拥有属于自己的api管理器)

    在大型的项目中,如果你有非常多的接口需要统一管理,或者需要进行接口测试,那么我们通常会在繁杂地api中找到需要进行测试或者管理的接口,接下来通过本文给大家介绍springboot集成Swagger的方法让你拥有属于自己的api管理器,感兴趣的朋友一起看看吧
    2021-11-11
  • Idea设置全局highlighting level为Syntax问题

    Idea设置全局highlighting level为Syntax问题

    这篇文章主要介绍了Idea设置全局highlighting level为Syntax问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04

最新评论