CompletableFuture 基本用法
一、 CompletableFuture简介
CompletableFuture
是 Java 8 引入的一个功能强大的类,用于异步编程和并发处理。它提供了丰富的 API 来处理异步任务的结果,支持函数式编程风格,并允许通过链式调用组合多个异步操作。
二、CompletableFuture中的方法
1. 创建 CompletableFuture 对象
CompletableFuture.supplyAsync(Supplier<U> supplier)
: 异步执行给定的Supplier
函数,并返回一个新的CompletableFuture
,当函数完成时,该CompletableFuture
将以函数的结果完成。
示例代码:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException; public class CompletableFutureExample { public static void main(String[] args) throws ExecutionException, InterruptedException { // 使用 supplyAsync 异步执行一个计算 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // 模拟一个耗时的计算 try { Thread.sleep(2000); // 等待 2 秒 } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IllegalStateException(e); } return "Hello, CompletableFuture!"; }); // 主线程可以继续执行其他任务,而不需要等待上面的计算完成 // 当需要结果时,可以调用 get() 方法(这会阻塞,直到结果可用) String result = future.get(); // 这里会等待上面的计算完成,然后返回结果 System.out.println(result); // 输出 "Hello, CompletableFuture!" }
}
这里顺便讲一下get方法:
(1)get方法的作用是等待此 CompletableFuture
完成,然后返回其结果(或抛出异常)。
(2)get方法的返回值是CompletableFuture<T> 里面的泛型的类型;比如上面的例子中CompletableFuture<String> 泛型是String 所以这里future.get()的返回值是String类型
示例1:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException; public class CompletableFutureExample { public static void main(String[] args) throws ExecutionException, InterruptedException { CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { ...... }); String result = future.get(); // 因为 CompletableFuture<String> 泛型是String 所以这里future.get()的返回值是String类型}
}
示例2:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException; public class CompletableFutureExample { public static void main(String[] args) throws ExecutionException, InterruptedException { CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> { ...... }); Integerresult = future.get(); // 因为 CompletableFuture<Integer> 泛型是Integer所以这里future.get()的返回值是Integer类型}
}
另外,supplyAsync
方法还有一个重载版本,它接受一个 Executor
作为参数,允许你指定用于执行计算的线程池。这对于控制异步任务的执行环境非常有用。例如:
ExecutorService executor = Executors.newFixedThreadPool(10); // 创建一个固定大小的线程池
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // ... 耗时的计算 ...
}, executor); // 使用指定的线程池执行计算
CompletableFuture.runAsync(Runnable runnable)
: 异用于异步地执行一个Runnable
任务,并且不返回任何结果(返回类型为CompletableFuture<Void>
)。这在你只关心任务的执行而不关心其返回值时非常有用。
import java.util.concurrent.CompletableFuture; public class CompletableFutureExample { public static void main(String[] args) { // 使用默认的 ForkJoinPool 异步执行任务 CompletableFuture<Void> future = CompletableFuture.runAsync(() -> { // 模拟一个耗时的任务 try { Thread.sleep(2000); // 假设任务需要2秒来完成 } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复中断状态 throw new RuntimeException(e); // 抛出运行时异常以便可以看到异常信息 } System.out.println("任务执行完毕!"); }); // 在主线程中继续执行其他操作,不需要等待上面的任务完成 System.out.println("主线程继续执行..."); // 如果你想等待任务完成,可以调用 future.join() 或 future.get(),但请注意这可能会阻塞当前线程 // 这里我们只是打印出任务是否已经完成 System.out.println("任务是否完成: " + future.isDone()); // 注意:由于任务是异步执行的,所以上面的 isDone() 方法可能返回 false,因为任务可能还没有完成 // 你可以通过 future.thenRun(...) 来添加在任务完成后要执行的代码 future.thenRun(() -> System.out.println("任务完成后执行的代码")); // 注意:thenRun 中的代码也是异步执行的,并且可能在主线程之后执行 // 为了确保主线程在异步任务完成后才结束,可以调用 future.join() try { future.join(); // 等待异步任务完成 } catch (Exception e) { e.printStackTrace(); } // 现在可以确定异步任务已经完成 System.out.println("主线程结束"); }
}
2. 处理异步任务的结果
thenApply(Function<? super T,? extends U> fn)
: 当此CompletableFuture
完成时,将结果应用于给定的函数,并返回一个新的CompletableFuture
,该CompletableFuture
将以函数的结果完成。thenAccept(Consumer<? super T> action)
: 当此CompletableFuture
完成时,对结果执行给定的操作,然后返回this
。thenRun(Runnable action)
: 当此CompletableFuture
完成时,执行给定的操作,然后返回this
。
3. 组合多个 CompletableFuture
thenCombine(CompletableFuture<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
: 当此CompletableFuture
和另一个给定的CompletableFuture
都完成时,使用这两个结果作为参数应用给定的函数,并返回一个新的CompletableFuture
,该CompletableFuture
将以函数的结果完成。
传统写法:
public static void main(String[] args) {CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {// 模拟耗时计算,返回结果try {Thread.sleep(1000); // 等待1秒} catch (InterruptedException e) {e.printStackTrace();}return 42; // 假设这是第一个任务的结果});CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {// 模拟耗时计算,返回结果try {Thread.sleep(500); // 等待0.5秒} catch (InterruptedException e) {e.printStackTrace();}return 13; // 假设这是第二个任务的结果});// 使用 thenCombine 合并两个任务的结果CompletableFuture<Integer> resultFuture = future1.thenCombine(future2, (a, b) -> a + b);// 等待结果并打印Integer join = resultFuture.join();System.out.println(join);//55}
链式调用:
public static void main(String[] args) {CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {// 模拟耗时计算,返回结果try {Thread.sleep(1000); // 等待1秒} catch (InterruptedException e) {e.printStackTrace();}return 42; // 假设这是第一个任务的结果}).thenCombine(CompletableFuture.supplyAsync(() -> {// 模拟耗时计算,返回结果try {Thread.sleep(500); // 等待0.5秒} catch (InterruptedException e) {e.printStackTrace();}return 13; // 假设这是第二个任务的结果}),(res1,res2)->{int total = res1 + res2;return total;});// 等待结果并打印Integer total = future1.join();System.out.println(total); // 42+13=55}
thenCompose(Function<? super T,? extends CompletionStage<U>> fn)
: 当此CompletableFuture
完成时,对其结果应用给定的函数,该函数返回一个新的CompletionStage
,然后返回表示该CompletionStage
结果的CompletableFuture
。
thenCompose
是 CompletableFuture
类中的一个方法,它允许你将一个 CompletableFuture
的结果用作另一个 CompletableFuture
计算的输入,从而链式地组合多个异步操作。
使用场景
thenCompose
适用于以下场景:
- 连续异步处理:当你需要对一个异步操作的结果进行另一个异步操作时,可以使用
thenCompose
将这两个操作连接在一起。 - 避免嵌套:使用
thenCompose
可以避免Future
的嵌套,使得代码更加简洁和平坦。
传统写法:
package com.etime.test;import java.util.concurrent.CompletableFuture;/*** @Date 2024/6/22 20:08* @Author liukang**/
public class SupplyAsyncTest {public static void main(String[] args) {CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {// 模拟耗时计算,返回结果try {Thread.sleep(1000); // 等待1秒} catch (InterruptedException e) {e.printStackTrace();}return 42; // 假设这是计算的结果});CompletableFuture<Integer> resultFuture = future.thenCompose(value -> {// 使用前一个任务的结果(value)作为输入,创建并返回一个新的CompletableFuturereturn CompletableFuture.supplyAsync(() -> value * 2); // 将结果乘以2});// 等待结果并打印Integer join = resultFuture.join();System.out.println(join);//84}}
链式调用:
public static void main(String[] args) {CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {// 模拟耗时计算,返回结果try {Thread.sleep(1000); // 等待1秒} catch (InterruptedException e) {e.printStackTrace();}return 42; // 假设这是计算的结果}).thenCompose(value -> CompletableFuture.supplyAsync(()->{return value*2;}));Integer join = future.join();System.out.println(join);}
allOf(CompletableFuture<?>... cfs)
: 返回一个新的CompletableFuture
,该CompletableFuture
在所有给定的CompletableFuture
都完成时完成。anyOf(CompletableFuture<?>... cfs)
: 返回一个新的CompletableFuture
,该CompletableFuture
在任何一个给定的CompletableFuture
完成时完成。
4. 异常处理
exceptionally(Function<Throwable,? extends T> fn)
: 当此CompletableFuture
异常完成时,应用给定的函数到异常,并返回一个新的CompletableFuture
,该CompletableFuture
将以函数的结果完成。
exceptionally
是Java中CompletableFuture
类的一个方法,用于处理异步操作中可能发生的异常。通过调用exceptionally
方法并定义一个异常处理函数,你可以确保在异步操作出现异常时能够优雅地处理,并返回一个默认值或其他的值。
public static void main(String[] args) {CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {// 模拟耗时计算,返回结果try {Thread.sleep(1000); // 等待1秒} catch (InterruptedException e) {e.printStackTrace();}return 42; // 假设这是计算的结果}).thenCompose(value -> CompletableFuture.supplyAsync(()->{return value/0;})).exceptionally((e -> {System.out.println("发生了异常");System.out.println("异常信息为:"+e.getMessage());return null;}));// 等待结果并打印Integer join = future.join();System.out.println(join);}
handle(BiFunction<? super T,Throwable,? extends U> fn)
: 当此CompletableFuture
完成时,无论是正常完成还是异常完成,都将结果和异常(如果有)应用于给定的函数,并返回一个新的CompletableFuture
,该CompletableFuture
将以函数的结果完成。
5. 其他方法
join()
: 等待此CompletableFuture
完成,然后返回其结果(或抛出异常),是get方法的升级版。get()
: 等待此CompletableFuture
完成,然后返回其结果(或抛出异常)。与join()
类似,但可能抛出InterruptedException
和ExecutionException
。
join()和get()的区别
- 抛出异常的方式不同:
get
方法会抛出ExecutionException
异常(如果异步任务执行过程中出现异常),这个异常是具体的,需要显式捕获。此外,如果线程在等待过程中被中断,它还会抛出InterruptedException
。join
方法则会抛出CompletionException
异常(如果异步任务执行过程中出现异常),这个异常是 unchecked 的,因此不需要显式捕获。如果线程在等待过程中被中断,它不会抛出InterruptedException
,因为它本身是不可中断的。
- 方法调用限制不同:
get
方法可以在调用时设置等待的超时时间,如果超时还没有获取到结果,就会抛出TimeoutException
异常。这使得get
方法在使用时具有更大的灵活性。join
方法则没有这样的超时机制,一旦调用就必须等待任务执行完成才能返回结果。它不能被中断,除非异步任务本身完成。
- 返回结果类型不同:
get
方法返回的是异步任务的执行结果,该结果是泛型类型T
的,需要强制转换才能获取真正的结果。join
方法同样返回的是异步任务的执行结果,但不需要强制类型转换,因为其结果就是泛型类型T
。
- 推荐使用方式不同:
join
方法通常被推荐用于CompletableFuture
,因为它没有受到interrupt
的干扰,不需要捕获异常,也不需要强制类型转换。这使得代码更加简洁和易于阅读。get
方法则提供了更多的控制选项,如设置超时时间,这在某些需要更细粒度控制的场景下可能是有用的。但需要注意的是,它可能会抛出InterruptedException
,这需要在代码中显式处理。
- 阻塞行为:
- 两者都是阻塞方法,都会阻塞当前线程直到异步任务完成。但如上所述,
join
方法是不可中断的,而get
方法可以被中断。
- 两者都是阻塞方法,都会阻塞当前线程直到异步任务完成。但如上所述,
总结来说,join
和 get
方法在 CompletableFuture
中都用于获取异步任务的执行结果,但在抛出异常的方式、方法调用限制、返回结果类型以及推荐使用方式等方面存在显著的区别。根据具体的需求和场景,可以选择使用 join
或 get
方法。
complete(T value)
: 如果尚未完成,则尝试以给定值完成此CompletableFuture
。completeExceptionally(Throwable ex)
: 如果尚未完成,则尝试以给定异常完成此CompletableFuture
。
这些只是 CompletableFuture
提供的一部分方法,但它已经足够强大,可以处理大多数异步编程和并发处理的场景。
相关文章:
CompletableFuture 基本用法
一、 CompletableFuture简介 CompletableFuture 是 Java 8 引入的一个功能强大的类,用于异步编程和并发处理。它提供了丰富的 API 来处理异步任务的结果,支持函数式编程风格,并允许通过链式调用组合多个异步操作。 二、CompletableFuture中…...
网页如何发布到服务器上
将网页发布到服务器上的过程涉及多个步骤,包括准备阶段、选择托管提供商、发布网站等。12 准备阶段: 确保在本地开发环境中对网站进行了充分的测试,包括功能测试、性能测试和安全测试。 检查Web.config文件,确保所有的配置设置…...
Jenkins简要说明
Jenkins 是一个开源的持续集成和持续部署(CI/CD)工具,广泛用于自动化软件开发过程中的构建、测试和部署等任务。它是基于Java开发的,因此可以在任何支持Java的平台上运行,并且能够与各种操作系统、开发工具和插件无缝集…...
C# 比较基础知识:最佳实践和技巧
以下是一些在 C# 中进行比较的技巧和窍门的概述。 1. 比较原始类型 对于原始类型(int、double、char 等),可以使用标准比较运算符。 int a 5; int b 10; bool isEqual (a b); // false bool isGreater (a > b); // false bool is…...
Ansible 自动化运维实践
随着 IT 基础设施的复杂性不断增加,手动运维已无法满足现代企业对高效、可靠的 IT 运维需求。Ansible 作为一款开源的自动化运维工具,通过简洁易用的 YAML 语法和无代理(agentless)架构,极大简化了系统配置管理、应用部…...
红队攻防渗透技术实战流程:中间件安全:IISNGINXAPACHETOMCAT
红队攻防渗透实战 1. 中间件安全1.1 中间件-IIS-短文件&解析&蓝屏等1.2 中间件-Nginx-文件解析&命令执行等1.2.1 后缀解析 文件名解析1.2.2 cve_2021_23017 无EXP有POC1.2.3 cve_2017_7529 意义不大1.3 中间件-Apache-RCE&目录遍历&文件解析等1.3.1 cve_20…...
如何卸载宝塔面板?
宝塔官方有提供宝塔面板的卸载命令,使用这个卸载命令,我们就能将宝塔面板卸载掉。 这里有一点需要注意的,如果卸载宝塔面板的同时,也希望将 Nginx、MySQL、PHP 等组件卸载掉,那么我们应该先在宝塔面板里面卸载掉以上软…...
python入门基础知识(错误和异常)
本文部分内容来自菜鸟教程Python 基础教程 | 菜鸟教程 (runoob.com) 本人负责概括总结代码实现。 以此达到快速复习目的 目录 语法错误 异常 异常处理 try/except try/except...else try-finally 语句 抛出异常 用户自定义异常 内置异常类型 常见的标准异常类型 语法…...
迈巴赫S480升级增强现实AR抬头显示hud比普通抬头显示HUD更好用吗
增强AR实景抬头显示HUD(Augmented Reality Head-Up Display)是一种更高级的驾驶辅助技术,相比于普通抬头显示HUD,它提供了更丰富、更具沉浸感的驾驶体验。以下是它比普通抬头显示HUD多的一些功能: • 信息呈现方式&am…...
vivado、vitis2022安装及其注意事项(省时、省空间)
1、下载 AMD官网-资源与支持-vivado ML开发者工具,或者vitis平台, 下载的时候有个官网推荐web安装,亲测这个耗时非常久,不建议使用,还是直接下载89G的安装包快。 注意:安装vitis平台会默认安装vivado&…...
【自动驾驶】ROS小车系统
文章目录 小车组成轮式运动底盘的组成轮式运动底盘的分类轮式机器人的控制方式感知传感器ROS决策主控ROS介绍ROS的坐标系ROS的单位机器人电气连接变压模块运动底盘的电气连接ROS主控与传感器的电气连接ROS主控和STM32控制器两种控制器的功能运动底盘基本组成电池电机控制器与驱…...
mysql学习——多表查询
多表查询 内连接外连接自连接自连接查询联合查询 子查询 学习黑马MySQL课程,记录笔记,用于复习。 添加外键 alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);多表查询 select * from emp , dept where emp…...
【Gradio】如何设置 Gradio 数据框的样式
简介 数据可视化是数据分析和机器学习的关键方面。Gradio DataFrame 组件是一种流行的方式,在网络应用程序中显示表格数据(特别是以 pandas DataFrame 对象的形式)。 本文将探讨 Gradio 的最新增强功能,这些功能允许用户整合 pand…...
【ThreeJS】Threejs +Vue3 开发基础
目前流行的前端3D框架以以Three.js、Babylon.js、A-Frame和ThingJS为例: 1.Three.js 功能: 提供了大量的3D功能,包括基本几何形状、材质、灯光、动画、特效等。 易用性: 功能强大且易于使用,抽象了复杂的底层细节&…...
cocos 如何使用九宫格图片,以及在微信小程序上失效。
1.在图片下方,点击edit。 2.拖动线条,使四角不被拉伸。 3.使用。 其他 在微信小程序上失效,需要将packable合图功能取消掉。...
Spring企业开发核心框架
一、框架前言 1、总体技术体系 单一架构 一个项目,一个工程,导出为一个war包,在一个Tomcat上运行。也叫all in one. 单一架构,项目主要应用技术框架为:Spring,SpringMVC,Mybatis等 分布式架构…...
Scrum团队在迭代中如何处理计划外的工作
认为 Scrum 团队不做计划其实是一个误区,实际上很多 Scrum 团队在冲刺计划会议以及在细化工作项时均会进行详细规划。此外,他们还会创建一个路线图,以便显示他们在多个冲刺中的计划。 Scrum 团队需要经常进行计划,以便在不断变化…...
桌面识别技术革新交互,展厅互动体验步入新时代!
在这股科技浪潮中,物体识别桌作为一种前沿的人机交互设备,其影响力尤为显著。它不仅颠覆了传统展厅内容的交互模式,更以科技之力为观众呈现了一场前所未有的视觉盛宴。那么,接下来,就让我们一起深入探索,物…...
书生·浦语大模型LagentAgentLego智能体应用搭建 第二期
文章目录 智能体概述智能体的定义智能体组成智能体范式 环境配置Lagent:轻量级智能体框架实战Lagent Web Demo用 Lagent 自定义工具 AgentLego:组装智能体“乐高”直接使用AgentLego作为智能体工具使用 用 AgentLego 自定义工具 智能体概述 智能体的定义…...
具有 Hudi、MinIO 和 HMS 的现代数据湖
Apache Hudi 已成为管理现代数据湖的领先开放表格式之一,直接在现代数据湖中提供核心仓库和数据库功能。这在很大程度上要归功于 Hudi 提供了表、事务、更新/删除、高级索引、流式摄取服务、数据聚类/压缩优化和并发控制等高级功能。 我们已经探讨了 MinIO 和 Hudi…...
32.基于分隔符解决黏包和半包
LineBasedFrameDecoder 基于换行/n (linux)或回车换行/r/n(windows)进行分割。 使用LIneBasedFrameDecoder构造方法,需要设定一个最大长度。 如果超过了最大长度,还是没有找到换行符,就这位这个数据段太长了,抛出ToolLongFrameException DelimiterBasedFrameDecoder …...
2024-6-19(沉默springboot)
1.spring开启事务支持 事务在逻辑上是一组操作,要么执行,要不都不执行。主要是针对数据库而言的,比如说 MySQL。 业务场景eg: public void savePosts(PostsParam postsParam) {// 保存文章save(posts);// 处理标签insertOrUpdateTag(posts…...
three.js 第八节 - gltf加载器、解码器
// ts-nocheck // 引入three.js import * as THREE from three // 导入轨道控制器 import { OrbitControls } from three/examples/jsm/controls/OrbitControls // 导入hdr加载器(专门加载hdr的) import { RGBELoader } from three/examples/jsm/loaders…...
Aquila-Med LLM:开创性的全流程开源医疗语言模型
论文链接:https://arxiv.org/pdf/2406.12182 开源链接:https://huggingface.co/BAAI/AquilaMed-RL http://open.flopsera.com/flopsera-open/details/AquilaMed_SFT http://open.flopsera.com/flopsera-open/details/AquilaMed_DPO 近年来…...
快速排序总结
标准模版 交换法 单函数法 public static void quickSort(int[] arr, int start, int end) {if (start > end) {return;}int idx start;int pivot arr[idx];int left start, right end;while (left < right) {while (left < right && arr[right] > …...
探索Linux的奇妙世界:第二关---Linux的基本指令1
1. xshell与服务器的连接 想必大家在看过上一期视频时已经搭建好了Linux的环境了并且已经下好了终端---xshell了吧?让我来带大家看一看下好了是什么样子的: 第一次登陆会让你连接你的服务器,就是我们买的云服务器,买完之后需要把公网地址ip复制过来进行链接,需要用户名和密码连…...
荒野大镖客2启动找不到emp.dll的7个修复方法,轻松解决dll丢失的办法
一、emp.dll文件丢失的常见原因 安装或更新问题:在软件或游戏的安装过程中,可能由于安装程序未能正确复制文件到目标目录,或在更新过程中文件被意外覆盖或删除,导致emp.dll文件丢失。 安全软件误删:某些安全软件可能…...
数据库精选题(三)(SQL语言精选题)(按语句类型分类)
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀数据库 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 前言 创建语句 创建表 创建视图 创建索引…...
Spring Boot + Apache Tika 实现文档内容解析
文章目录 1. 环境准备2. 创建 Spring Boot 项目2.1 初始化项目2.2 添加 Apache Tika 依赖 3. 创建文档解析服务3.1 创建服务类3.2 创建控制器类 4. 配置和运行4.1 配置 Apache Tika 数据文件4.2 运行应用程序 5. 测试和验证5.1 使用 Postman 或 cURL 进行测试 6. 注意事项和优化…...
AcWing 255. 第K小数
自己想出来的,感觉要容易想到,使用可持久化线段树,时间上要比y的慢一倍。大体思想就是,我们从小到大依次加入一个数,每加入一个就记录一个版本,线段树里记录区间里数的数量,在查询时,…...
高端品牌网站建设专人一对一服务/google关键词指数
标签(空格分隔): QCon 10.17-10.19在上海度过了Qcon的三天。今年的Qcon主题非常的散,这也是近两年无论ArchSummit还是QCon的一个特点,基本涵盖了以互联网技术为主的所有领域。 我个人主要关注还是云计算、机器学习和大…...
wordpress搬站流程/seo网站内部优化方案
我们对内存条是“情有独钟”,电脑卡了我们会直接加装内存条,游戏运行不流畅也会直接加装内存条,总之在很多人心中认为电脑内存条 就像电脑的“救世主”,那么,内存条在电脑中的作用究竟有多大呢?电脑内存条的…...
企业网站推广方式和策略/专业软文发布平台
宁波市第23届中小学生计算机程序设计竞赛复赛试题(小学组)宁波市第2届中小学生计算机程序设计竞赛复赛试题(小学组)题目一览试题名称 排名导游奖品英文代号 paimingdaoyoujiangpin程序名 .pas/c/cpp paiming.pas/c/cpp daoyou.pas/c/cpp jiangpin.pas/c/cpp 输入文件名 .in pai…...
可以做网站的电脑软件/网店代运营哪个好
一直以来写linux驱动,都是按照固定格式,定义一个初始化和推出函数,书上告诉我这两个函数会被调用,至于为什么会被调用,在哪调用,一直不清楚。 偶然的一个机会,看到blob里面的代码,里…...
浙江高速建设公司网站/广州网络广告推广公司
在数学中我们会遇到各种数学符号,有运算符号,希腊符号,还有表示逻辑关系的逻辑符号等,这些大多都是比较常用的符号。其中逻辑符号中我们经常会用到异或与非等,这些符号的编辑我们常常会需要用MathType这款公式编辑器&a…...
芜湖做网站/友情链接联盟
在手机上,ram是指运行内存,现在手机运行内存最大就是到4g,rom是指手机操作系统和机身存储内存,有的手机可以放入sd,也就相当于是增大了手机的rom。也可以说.ROM(Read Only Memory)的全名为唯读记忆体,它相当于PC机上的…...