新日撸java三百行` 新手小白java学习记录 `Day1

news/2024/11/13 15:51:22/

java_java__0">新日撸java三百行新手小白java学习记录

Day1 模拟多线程回调机制


文章目录

  • 新日撸java三百行` 新手小白java学习记录 `
  • 前言
  • 一 、模拟异步机制
  • 提出问题
  • 解决方案


前言

古人称长江为江,黄河为河。长江水清,黄河水浊,长江在流,黄河也在流。 长江之水灌溉了两岸数省之田地,黄河之水也灌溉了数省两岸之田地,只能不因水清而偏用,也只能不因水浊而偏废,自古皆然。


一 、模拟异步机制

提出问题

众所周知,java实现多线程可以实现Runnable、Callable两个接口,两者区别在于有无返回值。
目标:探究Callable的返回值如何返回的
问题:主线程中派生一个线程A执行有返回值的任务,如何解决主子线程时间差。

解决方案

使用一个已知的对象来承接返回值,命名为MyCompletableFuture。

  • 1.定义自已的任务实现接口myable类似Callable接口
java">public interface Myable<T> {T my();
}
  • 2.创建MyCompletableFuture类
    核心类,目的是截断子线程的返回值,使用该类代替子线程的返回值。
    大概逻辑:持有任务接口(符合里式替换原则),持有任务的返回值result, 持有标志位isComplete判断任务是否完成,持有还有一个自定义回调接口CallBack。
    – get()方法,调用该方法的线程会尝试获取任务的结果,此时有两种情况:任务完成和未完成。
    – submit()方法开启一个线程,调用任务接口的my方法执行任务并将返回值赋值给result,完成后调用Complete()方法
    – Complete()方法将标志位变成true标明任务完成;唤醒等待中的线程;调用回调。
java">public class MyCompletableFuture<T> {private Myable<T> myable;private T result;private Exception exception;private boolean isComplete = false;// private List<Function<T , ?>> callbacks = new ArrayList();private List<CallBack<T , ?>> callbacks = new ArrayList();public MyCompletableFuture() {}public MyCompletableFuture(Myable<T> myable) {this.myable = myable;}/*** 线程的启动方法 , 运行一个Myable的实现类 , 并接受返回值复制给当前类属性 , 而后调用Complete()方法。*/public void submit(){new Thread(()->{this.result = myable.my();try {Complete();} catch (Exception e) {throw new RuntimeException(e);}}).start();}/*** 当此方法被调用,说明返回值已经被成功接收 , 届时可以调整状态属性 , 唤醒调用get()的其他线程 , 执行回调。* @throws Exception*/private synchronized void  Complete() throws Exception {// this.result = result;isComplete = true;notifyAll();executeCallbacks();}public synchronized void completeExceptionally (Exception e){this.exception = e;this.isComplete = true;notifyAll();executeCallbacks();}/*** 判断返回值是否就绪 , 如果就绪则调用列表中的订阅者的回调函数 , 否则订阅该列表。* @param callback : 实现CallBack接口的回调方法* @return*/public synchronized MyCompletableFuture<Void> thenApply(CallBack<T , ?> callback){if(isComplete){if(exception != null){throw new RuntimeException(exception);}callback.callBack(result);}else {callbacks.add(callback);}return new MyCompletableFuture<>();}/*** 发布订阅模式执行回调。*/public synchronized void executeCallbacks(){for (CallBack<T, ?> callback: callbacks) {callback.callBack(result);}callbacks.clear();}/*** 获取返回值的方法,如果准备就绪则获取,否则wait();* @return* @throws Exception*/public synchronized T get() throws  Exception{if(!isComplete){wait();}if(exception != null){throw exception;}return result;}
}
  • 3.回调实现逻辑
    – 定义回调接口CallBack(函数式编程接口)
java">public interface CallBack<T , R> {R callBack(T t);
}

– 使用发布订阅模式在MyCompletableFuture中持有了一个CallBack类型的List,实现一个注册方法thenApply,当需要子线程结果的时候就调用thenApply方法

  • 4.使用案例
    定义任务类实现任务接口,任务就是对一个数组排序
java">class AsyncProcessor implements Myable<int[]>{int nums[] ;public AsyncProcessor(int[] nums) {this.nums = nums;}@Overridepublic int[] my() {try {Thread.sleep(1000);System.out.println("耗时排序中.......");Thread.sleep(2000);Arrays.sort(nums);} catch (InterruptedException e) {throw new RuntimeException(e);}return nums;}
}

主函数 将任务交给MyCompletableFuture

java">public class Main {public static void main(String[] args) throws Exception {int nums[] = new int[]{1,5,7,8,1,5,78,1,5,1};AsyncProcessor processor = new AsyncProcessor(nums);MyCompletableFuture<int[]> futureResult = new MyCompletableFuture<>(processor);futureResult.submit();futureResult.thenApply(result -> {System.out.println("最大值: " + result[nums.length-1]);return null; // 返回值为 void});futureResult.thenApply(result -> {System.out.println("最小值: " + result[0]);return null; // 返回值为 void});futureResult.thenApply(result -> {System.out.println("排序结果: " + Arrays.toString(result));return null; // 返回值为 void});// 在主线程继续执行其他操作System.out.println("请求已发送,等待处理结果...");// 获取结果(会阻塞直到完成)try {futureResult.get(); // 获取处理结果,等待完成} catch (Exception e) {e.printStackTrace();}}
}

在这里插入图片描述

总结:主线程想要不阻塞继续执行,必然会有一个已知的类型对象来接受返回值,进而将真正的返回值隐藏在该对象中。


http://www.ppmy.cn/news/1546712.html

相关文章

cesium 3DTiles之pnts格式详解

Point Cloud 1 概述 点云&#xff08;Point Cloud&#xff09;瓦片格式用于高效流式传输大规模点云数据&#xff0c;常用于 3D 可视化中。每个点由位置&#xff08;Position&#xff09;和可选的属性定义&#xff0c;这些属性用来描述点的外观&#xff08;如颜色、法线等&…

Spring Cloud微服务超详细讲解

Spring Cloud 是一个基于 Spring Boot 的微服务框架&#xff0c;它提供了一系列工具和服务来帮助开发者构建和管理微服务架构。以下是一个超级详细的讲解&#xff0c;涵盖了 Spring Cloud 的核心概念、组件以及如何构建一个简单的微服务应用。 1. 微服务架构概述 什么是微服务…

【开源免费】基于SpringBoot+Vue.JS医疗病历交互系统(JAVA毕业设计)

博主说明&#xff1a;本文项目编号 T 072 &#xff0c;文末自助获取源码 \color{red}{T072&#xff0c;文末自助获取源码} T072&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

Java从入门到精通笔记篇(十二)

枚举类型与泛型 枚举类型可以取代以往常量的定义方式&#xff0c;即将常量封装在类或接口中 使用枚举类型设置常量 关键字为enum 枚举类型的常用方法 values()方法 枚举类型实例包含一个values()方法&#xff0c;该方法将枚举中所有的枚举值以数组的形式返回。 valueOf()可…

初始化mysql5.7

-- 环境变量 MYSQL_HOME %MYSQL_HOME%\bin -- 新增配置文件 my.ini [mysqld] port 3306 basedir D:/develop/MySQL/mysql-5.7.44-winx64 datadir D:/develop/MySQL/mysql-5.7.44-winx64/data max_connections 200character-set-serverutf8 default-storage-engineINNODB …

科研绘图系列:R语言差异分析双侧柱状图(grouped barplot)

文章目录 介绍加载R包数据画图系统信息介绍 双侧柱状图(grouped barplot),也称为分组柱状图,是一种用于展示不同组别之间比较的数据可视化图表。它通过将不同组别的柱状图并排放置,可以直观地比较不同组在各个类别上的表现或特征。以下是双侧柱状图的一些关键特点和用途:…

VBA高级应用30例应用3在Excel中的ListObject对象:插入行和列

《VBA高级应用30例》&#xff08;版权10178985&#xff09;&#xff0c;是我推出的第十套教程&#xff0c;教程是专门针对高级学员在学习VBA过程中提高路途上的案例展开&#xff0c;这套教程案例与理论结合&#xff0c;紧贴“实战”&#xff0c;并做“战术总结”&#xff0c;以…

软考系统架构设计师论文:论多源数据集成及应用

试题二 论多源数据集成及应用 在如今信息爆炸的时代,企业、组织和个人面临着大量的数据。这些数据来自不同的渠道和资源,包括传感器、社交媒体、销售记录等,它们各自具有不同的数据格式、分布和存储方式。因此如何收集、整理和清洗数据,以建立一个一致、完整的数据集尤为重…