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; } }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
Stream distinct根据list某个字段去重的解决方案
这篇文章主要介绍了Stream distinct根据list某个字段去重,stream的distinct去重方法,是根据 Object.equals,和 Object.hashCode这两个方法来判断是否重复的,本文给大家介绍的非常详细,需要的朋友可以参考下2023-05-05
最新评论