高频面试题整理(二)

news2025/1/15 16:55:12

文章目录

  • 索引相关问题
    • 优化你的索引
  • 密集索引和稀疏索引
  • 如何定位并优化慢查询sql
  • MyISAM与InnoDB 关于锁方面的区别是什么?
    • MyISAM
    • InnoDB
    • 事务隔离级别
  • 多线程并发的相关问题
    • Thread中的start和run方法的区别
    • Thread和Runnable是什么关系?
    • 如何处理线程的返回值?
    • 线程的状态
    • sleep和wait方法的区别
    • notify和notifyAll的区别
    • 如何中断一个线程?
    • synchronized的底层实现原理
    • synchronized和ReentrantLock的区别
    • valitile 和synchronized 的区别
  • 线程池
    • 线程的大小如何选定?
  • Java异常体系
    • Error和Exceptionde的区别
    • Java异常的处理原则
    • 高效主流的异常处理框架
    • Java异常处理消耗异常的地方
  • 容器
    • Collection体系:
    • Map体系
    • HashMap,HashTable,ConccurentHashMap
  • J.U.C知识点梳理
    • BIO,NIO,AIO

索引相关问题

优化你的索引

平衡多路查找树 B-Tree
在这里插入图片描述

  • 根节点至少包括两个孩子
  • 树中每个节点最多含有m个孩子(m>=2)
  • 除根节点和叶节点外,其他节点至少有ceil(m/2)个孩子 向上取整
  • 所有的终端叶子节点都位于同一层

在这里插入图片描述
B + Tree
在这里插入图片描述
B+ 树是B树的变体,其定义基本与B树相同,除了:

  • 非叶子节点的子树指针与关键字个数相同
  • 非叶子节点的子树指针p[i],指向关键字 [ k[i],k[i+1] )的子树
  • 非叶子节点仅用来索引,数据都保存在叶子节点中
  • 所有叶子节点均有一个链指针指向下一个叶子节点

B+Tree更适合用来做存储索引

  • B+树的磁盘读写代价更低
  • B+树的查询效率更稳定
  • B+树更有利于对数据库的扫描

Hash索引:
在这里插入图片描述
hash索引的查询效率是很高的,hash索引是通过has函数运算后,只需要经过一次定位,就可以找到查询数据的头,不像B树要从根节点到非叶子节点再到叶子节点,最后才能访问到我们要查询的数据,这样就会进行多次I/O访问

缺点:

  • 仅能满足”=“ , ”IN“ ,不能使用范围查询
  • 无法用来避免数据的排序操作 (由于Hash索引中存放的是经过Hash算法运算后的值,而且Hash值的大小关系,并不一定和hash运算以前的键值完全一样)
  • 不能做组合索引查询
  • 不能避免表扫描
  • 运到大量Hash值相等的情况后,性能并不一定就会比B性能高

位图索引 ---------- 仅有Oracle支持
在这里插入图片描述

密集索引和稀疏索引

密集索引文件中的每个搜索码值都对应一个索引值------- 即叶子节点不仅保存了键值,还保存了位于同一条记录的其他列信息,由于密集索引决定了表的物理排列顺序,一个表只能创建一个密集索引

稀疏索引文件只为索引码的某些键建立索引项------- 即叶子节点只保存了键位信息以及索引主键

在这里插入图片描述
MySQL主要有两种存储引擎:
在这里插入图片描述
InnoDB ------------ 索引和数据是存在一块的

  • 若一个主键被定义,该主键列则作为密集索引
  • 若没有主键被定义,该表的唯一非空索引则作为密集索引
  • 若不满足以上条件,innodb内部会生成一个隐藏主键(密集索引)
  • 非主键索引存储相关键位和其对应的主键值,包含两次查找:

MYISAM ----------- 索引和数据是分开的

为什么要使用索引?
因为索引能让我们避免全表扫描去查找数据,提升检索效率

什么样的信息能成为索引?
主键,唯一键等,只要是能让数据具备一定区分性的字段,都能成为索引

索引的数据结构?
主流是B+树,还有Hash结构

如何定位并优化慢查询sql

根据慢日志定位慢查询sql

使用explain等工具分析sql

修改sql或者尽量让sql走索引

mysql有很多系统变量,查询和慢日志相关的配置信息,慢日志就是用来记录执行比较慢的sql

show variables like '%quer%' -------- 关注慢日志,打开慢日志,查看慢日志时间

show status like '%slow_queries%' ---------- 慢查询sql的数量

set global slow_query_log = on ----------- 打开慢日志,这个是临时改变的,重启数据库又会到默认值

set global long_query_time = 1 ------- 设置慢查询的时间为1s

关键字type字段:index,all就代表实在全表扫描了,需要进行sql优化
在这里插入图片描述
extra
在这里插入图片描述
最左匹配原则:非常重要的原则,mysql会一直向右匹配直到范围查询(<,>,between,like)就停止匹配,比如a=3,b=4, and c>5 and d=6 ,建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则可以用到

索引建立的越多越好吗?

  • 数据量小的表不需要建立索引,建立会增加额外的索引开销
  • 数据变更需要维护索引,因此更多的索引意味着的更多的维护成本
  • 更多的索引意味着也需要更多的空间

MyISAM与InnoDB 关于锁方面的区别是什么?

MyISAM默认用的是表级锁,不支持行级锁

InnoDB默认用的是行级锁,也支持表级锁

MyISAM

读锁 ------ 共享锁 lock tables 表名 read

对表加上读锁时,在进行范围查询时,其他人仍然可以对数据进行查询
写锁-------- 排它锁

需要等待写锁的释放,才能执行其他语句

InnoDB

当不走索引时,就会使用表级锁,若SQL用到了索引,就会使用行级锁

MYISAM使用的场景:

  • 频繁执行全表count语句
  • 对数据进行增删改的频率不高,查询非常频繁
  • 没有事务

InnoDB使用的场景

  • 数据库的增删改查都相当频繁
  • 可靠性要求比较高,支持事务

数据库锁的分类

  • 按锁的粒度划分:可分为表级锁,行级锁,页级锁
  • 按锁的级别划分:共享锁,排它锁
  • 按加锁的方式划分:可分为自动锁,显示锁
  • 按操作划分:可分为DML锁,DDL锁
  • 按使用方式划分:可分为乐观锁,悲观锁
    • 悲观锁:对数据,对外界的修改持保守态度,基于数据库的锁机制,先锁再访问,是对安全的一种保证,但该方式效率低,而且容易造成死锁
    • 乐观锁:认为数据一般情况不会造成冲突,所以在数据提交更新的时候,才会检查数据是否冲突,如果发现冲突,则返回用户的错误信息,让用户决定如何去做,相对于悲观锁,在对数据库进行操作时,乐观锁并不会使用数据库提供锁机制。一般实现乐观锁的方式就是记录数据版本-------通过版本号或者时间戳 ------- 增加一个数字类型version列

事务隔离级别

select @@tx_isolation 查看事务的隔离级别

set session transaction isolation level read uncommited 设置当前会话窗口的事务隔离级别为 读未提交,该方式会发生脏读,即允许读到其他事务未提交的数据

start transction; 开启手动事务

**事务并发访问引起的问题以及如何避免?**考察事物的隔离级别
在这里插入图片描述
InnoDB可重复读隔离级别下,如何避免幻读?
表象:快照度(非堵塞读)— 伪MVCC(多版本并发控制)
当前读:select .... lock in share mode select .... for update, insert update delete

在这里插入图片描述

快照读:不加锁的非阻塞读,在可重复读级别下可能读取到之前版本的数据,取决于快照的时间

RC,RR级别下的InnoDB的非阻塞读(快照度)如何实现?
1.数据行里的DB_TRX_ID(事务id),DB_ ROLL_PTR(回滚指针),DB_ROW_ID(行号)字段

2.undo日志
日志的工作方式:这里以更新为例
在这里插入图片描述

在修改前,先将数据拷贝一份到Undo log中
在这里插入图片描述
数据的各个版本就是这样实现的,按照修改的时间,从近代远,按照DB_ROLL_PTR连接起来

3.read view 做可见性判断,根据可见性算法,显示可以看见的数据版本

内在:next-key锁(行锁+gap锁)

  • 行锁:对某条记录加锁
  • Gap锁:避免两次当前读,出现幻读

对主键索引或者唯一索引会用Gap锁吗?

  • 如果where条件全部命中,则不会用Gap锁,只会使用行级锁
  • 如果where条件部分命中或者全部不命中,则会使用Gap锁
  • Gap索引会用在非唯一索引或者不走索引的当前读中

多线程并发的相关问题

Thread中的start和run方法的区别

调用start()方法会创建一个新的子线程并启动

run()方法只是Thread的一个普通方法的调用

Thread和Runnable是什么关系?

Thread是实现了Runnable接口的类,使得run支持多线程

因类的单一继承原则,推荐多使用Runnable接口

如何处理线程的返回值?

主线程等待法------------- 让主线程循环等待,需要自己实现循环等待的逻辑,无法控制循环的时间

使用Thread类的join()阻塞当前线程以等待子线程处理完毕 -------- 无法可控制粒度更细的依赖关系

通过Callable接口,通过FutureTask 或者 线程池获取

实现Callable接口,重写含有返回值的Call方法,FutureTask的构造函数中需要一个Callable接口实现类的对象,futureTask是间接继承Runable接口的,所以可以将FutureTask对象传入到Thread构造函数中

线程的状态

在Thread源码中,有一个State的枚举类型,该枚举类型中有6个值
从源码和官方说明中,线程有6个状态

  • 新建(New):创建后尚未启动的线程的状态
  • 运行(Runnable):包含Running和Ready
  • 无限等待(Waitting):不会被分配CPU执行时间,需要显式被唤醒
    造成无限等待的情况:没有设置Timeout参数的Object.wait()方法;没有设置Timeout参数的Thread.join()方法,调用LockSupport.park()方法
  • 限期等待(Timed Waitting):在一定时间后会由系统自动唤醒
    出现情况:Thread.sleep()方法;设置Timeout参数的Object.wait()方法;设置了Timeout参数的Thread.join()方法,LockSupport.parkName()方法;LockSupport.parkUntil()方法,都需要传入时间参数
  • 阻塞(Blocked):等待获取排它锁
  • 结束(Terminated):已终止线程的状态,线程已结束执行

sleep和wait方法的区别

基本差别:

  • sleep是Thread类中的方法,wait是Object类中定义的方法
  • sleep()方法可以在任何地方使用,而wait()方法只能在synchronized方法或在synchcronized代码块中使用(因为需要获取锁后才能释放锁)

本质区别:

  • Thread.sleep只会让出CPU,不会释放锁,会一直持有锁
  • Object.wait不仅会让出CPU,还会释放已占有的同步锁

notify和notifyAll的区别

锁池:假设线程A已经拥有了某个对象锁,而其他线程B,C想要调用这个对象的某个synchronized方法或者代码块之前必须获得该对象的锁,而恰巧该对象的锁正被A线程占用,此时B,C线程就会被阻塞,进入一个地方去等待锁的释放,这个地方就是该对象的锁池

等待池:假设线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁,同时线程A就进入了该对象的等待池中,进入的等待池的线程不会去竞争该对象的锁

notifyAll会让所有处于等待池中的线程,全部进入锁池去竞争获取锁的机会

notify只会随机选取一个处于等待池中得线程,进入锁池中去竞争获取锁的机会

yield:当调用Thread,yield()方法时,会给线程调度器一个当前线程愿意让出CPU使用的暗示,但是线程调度器可能会忽视这个暗示

如何中断一个线程?

已被抛弃的方法:通过调用stop()方法停止线程 -------- 可以由一个线程调用stop方法,终止另一个线程,该方法太过暴力,而且是不安全的

线程A调用线程B的stop方法,去停止线程B,但线程A其实并不知道线程B的具体执行情况,这种突然的停止动作会导致线程B的一些清理工作无法完成,还有就是执行stop方法后,线程B会马上释放自己的锁,这样有可能会引发数据不同步的问题

目前使用的方法:调用interrupt()方法,通知线程应该中断了

  1. 如果线程处于被阻塞状态,那么线程应该立即退出被阻塞状态,并抛出一个InterruptExceptioon异常
  2. 如果线程处于正常活动状态,那么将该线程的中断标志设置为true,被设置中断标志的线程将继续正常运行,不受影响。

因此Interrupt并不能真正是线程中断,需要被调用的线程配合中断

线程状态以各个状态之间的转换:
在这里插入图片描述

synchronized的底层实现原理

实现synchronized的基础

  • Java对象头
  • Monitor
  • 对象在内存中的布局
  • 对象头
  • 实例数据
  • 对齐填充
    +对象头结构:
    • Mark Word 默认存储对象的hashcode,分代年龄,锁类型,锁标志位等信息,是实现轻量级锁和偏向锁的关键
    • Class Metadata Address 类型指针指向对象的元素类型,JVM通过这个指针确定该对象是哪个类的数据类型
  • Monitor:每个Java对象天生自带了一把看不见的锁

自旋锁与自适应自旋锁
许多情况下,共享锁的锁定状态持续时间较短,切换线程不值得,通过让线程执行忙循环等待锁的释放,不让出CPU;若锁被其他线程很长时间占用,会带来许多性能上的开销

自适应自旋锁:自旋的次数不在固定,由前一次在同一个锁上的自旋时间及锁的拥有者状态来定

锁消除:JVM对锁另一种更彻底的优化,JVM在JIT编译时,对运行上下文进行扫描,去除不可能存在竞争的锁。

锁粗化:另一种极端:通过扩大锁的范围,避免反复加锁和解锁

synchronized的四种状态
无锁 —> 偏向锁—> 轻量级锁 —>重量级锁

偏向锁:减少获取同一锁的代价 CAS(Compare And Swap)

大多数情况下,锁不存在多线程竞争,总是由一个线程多次获得

核心思想:如果一个线程获得了锁,那么锁就进入偏向模式,此时Mark Word的结构也变为偏向所的结构,当该线程再次请求锁时,无需再做任何同步操作,及获取锁的过程只需要检查Mark Word的锁标记位为偏向锁以及当前线程Id等于Mark Word的ThreadId即可,这样就省去了大量有关锁申请的操作

不适用于锁竞争比较激烈的多线程场合

轻量级锁:轻量级锁是由偏向锁升级来的,偏向锁运行在一个线程进入同步快的情况下,而第二个线程加入锁争用的时候,偏向锁就会升级位

轻量级锁:适应的场景:线程交替执行同步快
若存在同一时间访问同一锁的情况,就会导致轻量级锁升级到重量锁

在这里插入图片描述

synchronized和ReentrantLock的区别

  • ReentranLock(再入锁)
  • 位于java,util,concurrent,locks包
  • 和CountDownLatch,FutureTask,Semaphore一样基于AQS实现
  • 能够实现比synchronized更细粒度的控制,如控制faireness
  • 调用lock()后,必须调用unlock()释放锁
  • 性能未必比synchronized高,并且也是可重入的

ReentranLock公平性的设置
ReentanLock faireLock = new ReentanLock(true)
参数为true时,倾向于将锁赋予等待时间最长的线程

公平锁:获取锁的先后顺序按先后调用Lock()方法的顺序

非公平锁:抢占顺序不一定,看运气

synchronized是非公平锁

总结

  • synchronized是关键字,ReentraLock是类
  • ReentranLock可以对获取锁的等待时间进行设置,避免死锁
  • ReentranLock可以获取各种锁的信息
  • ReentranLock可以灵活地实现多路通知

机制:sync操作Mark Work,lock调用Unsafe类的park()方法

在这里插入图片描述
指令重排需要满足的条件:

  • 在单线程环境下不能改变程序执行的结果
  • 存在数据依赖关系的不允许重排序
  • 无法通过happends-before原则推导出来的,才能进行指令的重排

valitile 和synchronized 的区别

  1. volitile 本质是告诉JVM当前变量在工作内存中的值是不确定的,需要从主内存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞直到该线程完成变量操作为止
  2. volitile仅能使用在变量级别,synchronized则可以用在变量,方法和类级别
  3. volitile 仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量修改的可见性和原子性
  4. valitile不会造成线程的阻塞,synchronized则可能会造成线程的阻塞
  5. valitile标记的变量不会被编译器优化,synchronized标记的变量可以被编译器优化

CAS(Compare And Swap):一种高效实现线程安全性的方法
支持原子更新操作,适用于计数器,序列发生器等操作

属于乐观锁机制,号称lock-free

CAS操作失败时由开发者决定是继续尝试,还是执行别的操作

CAS多数情况下对开发者来说是透明的

J.U.C的atomic包提供了常用的原子性数据类型以及引用,数组等相关原子类型的更新操作工具,是很多线程安全的首选

Unsafe类虽然提供CAS服务,但因为能够操作任意内存地址读写而又隐患

缺点:若循环时间长,则开销很大,只能保证一个共享变量的原子操作,ABA问题

线程池

在web开发中,服务器需要接收并处理请求,所以会为一个请求来分配一个线程来进行处理,如果并发的请求数量比较多,但每个线程执行的时间很短,这样就会频繁的创建和销毁线程,这样一来就会大大降低系统的效率,可能出现服务器在为每个线程创建和销毁的时间比实际处理请求消耗的时间更多

利用Excutors创建不同的线程池满足不同场景的需求

  1. newFixedThreadPool(int nThreads) ------ 指定工作线程数量的线程池
  2. newCachedThreadPool() -------- 处理大量短时间工作任务的线程池
    • 试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程
    • 如果线程闲置时间超过阈值,则会被终止并移出缓存
    • 系统长时间闲置的时候,不会消耗什么资源
  3. newSingleThreadScheduledExcutor() newScheduledThreadPool(int corePoolSize)
    定时或者周期的工作调度,两者的区别在于单一工作线程还是多个线程
  4. newSingleThreadEcecutor()
    创建唯一的工作者线程来执行任务,如果线程异常结束,会有另一个线程取代

为什么要使用线程池
降低资源消耗
提高线程的可管理性

J.U.C的三个Excutor接口
Excutor:运行新任务的简单接口,将任务提交和任务执行细节解耦
ExcutorService:具备管理执行器和任务生命周期的方法,提交任务机制更完善
ScheduledExcutorService:支持Future的定期执行任务

在这里插入图片描述
TreadPoolExcutor的工作模式如图:
在这里插入图片描述
ThreadPoolExcutor的构造函数:

  • corePoolSize:核心线程数量
  • maximumPoolSize:线程不够用时能够创建 的最大线程数
  • workQueue:任务等待队列
  • keepAliveTime:抢占的顺序不一定,看运气
  • threadFactory:创建新线程,Excutors.defaultThreadFactory(),优先级不变,也设置了线程名称
  • handler:线程池的饱和策略
    • AbortPolicy:直接抛出异常,默认策
    • CallerRunsPolicy:用调用者所在的线程来执行任务
    • DiscardOldsPolicy:丢弃队列中最靠前的任务,并执行当前任务
    • DiscardPolicy:直接丢弃任务
    • 实现RejectExcutorHandler接口的自定义handler

新任务提交excutor执行后的判断:

  • 如果运行的线程少于corePoolSize,则创建新线程来处理任务,即使线程池中的其他线程是空闲的;
  • 如果线程池中的线程数量大于corePoolSize且小于maximumPoolSize,则只有当workQueue满时,才创建新的线程去处理任务
  • 如果设置的corePoolSizemaximumPoolSize相同,则创建的线程池大小是固定得,这时如果有新任务提交,若workQueue未满,则将请求放入workQueue中,等待有空闲的线程去从workQueue中去取任务并处理;
  • 若运行的线程数量大于等于maximumPoolSize,这时如果workQueue已经满了,则通过handler所指定的策略来处理任务

线程池的状态

  • Running :能接收新提交的任务,并且也能处理阻塞队列中的任务
  • shutdown:不再接收新提交的任务,但可以处理存量任务
  • stop:不再接收新提交的任务,也不处理存量任务
  • Tidying:所有 的任务都已终止
  • TERMINATED:terminated()方法执行后进入该状态

在这里插入图片描述
在这里插入图片描述

线程的大小如何选定?

CPU密集型:线程数 = 按照核数或者核数+1设定

I/O密集型:线程数 = CPU数 * (1+平均等待时间/平均工作时间 )

Java异常体系

Error和Exceptionde的区别

Error:程序无法处理的系统错误,编译器不做任何检查

Exception:程序可以处理的异常,捕获后可能恢复

总结:前者是程序无法处理的错误,后者是程序可以处理的异常

Java异常的处理原则

具体明确:抛出的的异常应该能通过异常类名和message准确说明异常的类型和产生异常的原因;

提早抛出:应尽可能早的发现并抛出异常,便于精确定位问题;

延迟捕获:异常的捕获和处理应尽可能延迟,让掌握更多信息的作用域来处理异常

高效主流的异常处理框架

在用户看来,应用系统发生的所有异常都是应用系统内部的异常

设计一个通用的继承自RuntimeException的异常来统一处理,设为AppException

其余异常都统一转义为上述异常AppException

在catch之后,抛出上述异常的子类,并提供足以定位的信息
由前端接收AppException做统一处理

Java异常处理消耗异常的地方

try-catch代码块影响JVM的优化

异常对象实列需要保存堆栈快照等信息,开销较大

容器

Collection体系:

在这里插入图片描述

Map体系

在这里插入图片描述

HashMap,HashTable,ConccurentHashMap

HashMap(Java8以前):数组+链表

Java8及以后:数组+链表+红黑树:当链表的长度大于8时,就会转为红黑树

HashMap:put方法的逻辑

  1. 如果HashMap未被初始化过,则初始化
  2. 对key求Hash值,然后在计算下标
  3. 如果没有碰撞,直接放入桶中
  4. 如果碰撞了,以链表的方式连接到后面
  5. 如果链表长度超过域值,就把链表转为红黑树
  6. 如果链表长度小于6,就把红黑树转回链表
  7. 如果节点已经存在,就会替换旧值
  8. 如果桶满了(容量16*加载因子0.75),就需要resize(扩容2倍后重排)

HashMap:如何有效减少碰撞

  • 扰动函数:促使元素位置分布均匀,减少碰撞几率
  • 使用final对象,并采用合适的equals()和hashCode()方法
    HashMap:扩容的问题
  • 多线程环境下,调整大小会存在条件竞争,容易造成死锁
    reHashing是一个比较耗时的过程

如何优化Hashtable?
通过锁细粒度化,将整锁拆解成多个锁进行优化

在这里插入图片描述
在这里插入图片描述
ConcurrentHashMap:put方法的逻辑

  1. 判断Node[]数组是否初始化,没有则进行初始化操作
  2. 通过hash定位数组的索引坐标,是否有Node节点,如果没有则使用CAS进行添加(链表的头节点),添加失败则进入下次循环
  3. 检查到内部正在扩容,就帮助他一块扩容
  4. 如果 f != null ,则使用synchronized锁住 f 元素(链表/红黑二叉树的头元素)
    • 如果Node(链表结构)则执行链表的添加操作
    • 如果是TreeNode(树形结构),则执行树的添加操作
  5. 当链表达到临界值8时,这个8是默认值,可以自己去调整,当节点树超过这个值就需要把链表转为树结构

三者的区别?

  • HashMap线程不安全,数组+链表+红黑树
  • Hashtable线程安全,锁住整个对象,数组+链表
  • ConcurrentHashMap线程安全,CAS+同步锁,数组+链表+红黑树
  • HashMap的key,value均可为null,而其他的两个类不支持

J.U.C知识点梳理

java,util.concrrent:提供了并发编程的解决方案

  • CAS :是java,util,concrrent.atomic包的基础
  • AQS:是java,util,concrrent.locks包及一些常用类,比如Semophore,ReentranLock等类的基础

J.U.C包的分类

  • 线程执行器executor
  • 锁 locks
  • 原子变量类 atomic
  • 并发工具类 tools
  • 并发集合 collections
    在这里插入图片描述

BIO,NIO,AIO

Block-IO:inputStream和OutputStream,Reader和Writer
在这里插入图片描述
NonBlock-IO:构建多路复用,同步非阻塞的IO操作
在这里插入图片描述
NIO的核心

  • Channels
    • FileChannel
      • transferTo:把fileChannel中的数据拷贝到另外一个Channel
      • transferFrom:把另外一个Channel中的数据拷贝到FileChannel。避免了两次用户态和内核态之间的切换,即“零拷贝”,效率较高
    • DatagramChannel
    • SocketChannel
    • ServerSocketChannel
  • Buffers
  • Selectors
    在这里插入图片描述
    Asynchronous IO:基于事件和回调机制
    在这里插入图片描述
    AIO如何进一步加工处理结果
  • 基于回调:实现CompletionHandler接口,调用时触发回调函数
  • 返回Future:通过isDone()查看是否准备好,通过get()等待返回数据

更多面试题、电子书、学习路线、视频教程等学习资源,可在我的个人网站:程序员波特 免费获取。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1470816.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java程序设计】【C00307】基于Springboot的基Hadoop的物品租赁管理系统(有论文)

基于Springboot的基Hadoop的物品租赁管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的基于 Hadoop的物品租赁系统的设计与实现&#xff0c;本系统有管理员、用户二种角色权限&#xff1b; 前台首页&#…

Xcode与Swift开发小记

引子 鉴于React Native目前版本在iOS上开发遇到诸多问题&#xff0c;本以为搞RN只需理会Javascript开发&#xff0c;没想到冒出CocoaPod的一堆编译问题。所以横下一条心&#xff0c;决定直接进攻iOS本身。不管你是用React Native&#xff0c;还是用Flutter&#xff0c;iOS下的…

记录一些mac电脑重装mysql和pgsql的坑

为什么要重装,是想在mac电脑 创建data目录…同事误操作,导致电脑重启不了.然后重装系统后,.就连不上数据库了.mysql和pgsql两个都连不上.网上也查了很多资料.实在不行,.就重装了… 重装mysql. 1.官网下载 https://www.mysql.com/downloads/ 滑到最下面 选择 选择对应的芯片版本…

python-产品篇-游戏-开心消消乐

文章目录 准备代码效果 准备 安装对应环境库 代码 import pygame import random from pygame.locals import *class SoundPlay:game_bgm "sound/GameSceneBGM.ogg"world_bgm sound/WorldSceneBGM.oggeliminate (sound/eliminate1.ogg, sound/eliminate2.ogg, s…

MATLAB环境下基于洗牌复杂演化的图像分割算法

智能优化算法因其较强的搜索解能力而得到了大量的应用&#xff0c;在这些计算智能算法中&#xff0c;群体智能优化算法因其高效性、有效性以及健壮性等优点而得到了科研人员的青睐。这类算法借鉴生物群体的合作特性&#xff0c;主要解决大规模复杂的分布式问题&#xff0c;研究…

YOLO算法改进Backbone系列之:EfficientViT

EfficientViT: Memory Effificient Vision Transformer with Cascaded Group Attention 摘要&#xff1a;视觉transformer由于其高模型能力而取得了巨大的成功。然而&#xff0c;它们卓越的性能伴随着沉重的计算成本&#xff0c;这使得它们不适合实时应用。在这篇论文中&#x…

深入理解 JavaScript 中的绑定机制(上)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Orange3数据预处理(列选择组件)数据角色及类型描述

在Orange3的文件组件中&#xff0c;datetime、categorical、numeric以及text代表不同种类的数据类型&#xff0c;具体如下&#xff1a; datetime&#xff1a;代表日期和时间类型的数据。通常用于时间序列分析、生存分析和其他需要考虑时间因素的机器学习任务中。例如&#xff0…

k8s-kubeapps部署 20

部署kubeapps应用&#xff0c;为Helm提供web UI界面管理&#xff1a; 下载最新版本的kubeapps并修改其values.yaml文件 下载并拉取所需镜像&#xff1a; 部署应用 添加解析 修改svc暴露方式为LoadBalancer 得到分配地址 访问http://192.168.182.102 授权并获取token 1.24前的…

密码学及其应用(应用篇15)——0/1背包问题

1 问题背景 背包问题是一个经典的优化问题&#xff0c;在计算机科学和运筹学中有着广泛的应用。具体到你提到的这个问题&#xff0c;它是背包问题中的一个特例&#xff0c;通常被称为0/1背包问题。这里&#xff0c;我们有一系列的正整数 &#xff0c;以及一个正整数&#xff0c…

TCP/IP协议栈:模拟器实现基本的L2和L3功能

在C中实现的TCPI/IP网络堆栈模拟器。该模拟器实现基本的第2层&#xff08;MAC地址&#xff0c;Arp&#xff09;和第3层&#xff08;路由&#xff0c;IP&#xff09;功能。 TCP/IP协议栈是一个网络通信的基础架构&#xff0c;包含了多层次的协议和功能。在模拟实现基本的L2和L3…

LabVIEW和Python开发微细车削控制系统

LabVIEW和Python开发微细车削控制系统 为满足现代精密加工的需求&#xff0c;开发了一套基于LabVIEW和Python的微细车削控制系统。该系统通过模块化设计&#xff0c;实现了高精度的加工控制和G代码的自动生成&#xff0c;有效提高了微细车削加工的自动化水平和编程效率。 项目…

【JavaEE】 spring boot的配置文件详解

spring boot的配置文件详解 文章目录 spring boot的配置文件详解常用配置spring boot的配置文件1. properties 文件2. YAML 文件3. 多环境配置4. 配置文件优先级5. 配置属性注入特殊说明 properties配置文件基本语法 例子peoperties文件的缺点 YML配置文件YML使用yml 配置不同数…

【PyQt5桌面应用开发】3.Qt Designer快速入门(控件详解)

一、Qt Designer简介 Qt Designer是PyQt程序UI界面的实现工具&#xff0c;可以帮助我们快速开发 PyQt 程序的速度。它生成的 UI 界面是一个后缀为 .ui 的文件&#xff0c;可以通过 pyiuc 转换为 .py 文件。 Qt Designer工具使用简单&#xff0c;可以通过拖拽和点击完成复杂界面…

mini-spring|向虚拟机注册钩子,实现Bean对象的初始化和销毁方法

目标 当我们的类创建的 Bean 对象&#xff0c;交给 Spring 容器管理以后&#xff0c;这个类对象就可以被赋予更多的使用能力。我们还希望可以在 Bean 初始化过程&#xff0c;执行一些操作。比如帮我们做一些数据的加载执行&#xff0c;链接注册中心暴漏RPC接口以及在Web程序关…

vSphere高可用架构---HA简介

1.高可用性 2.不同级别的高可用&#xff1a; 1&#xff09;应用程序级别&#xff0c;2&#xff09;操作系统级别&#xff0c;3&#xff09;虚拟化级别&#xff0c;4&#xff09;物理层级别 不同级别的高可用举例&#xff1a; 应用程序级别的高可用性。例如&#xff1a;Oracl…

高温应用中GaN HEMT大信号建模的ASM-HEMT

来源&#xff1a;An ASM-HEMT for Large-Signal Modeling of GaN HEMTs in High-Temperature Applications&#xff08;JEDS 23年&#xff09; 摘要 本文报道了一种用于模拟高温环境下氮化镓高电子迁移率晶体管&#xff08;GaN HEMT&#xff09;的温度依赖性ASM-HEMT模型。我…

机器学习.线性回归

斯塔1和2是权重项&#xff0c;斯塔0是偏置项&#xff0c;在训练过程中为了使得训练结果更加精确而做的微调&#xff0c;不是一个大范围的因素&#xff0c;核心影响因素是权重项 为了完成矩阵的运算&#xff0c;在斯塔0后面乘x0&#xff0c;使得满足矩阵的转换&#xff0c;所以在…

UE5 文字游戏(1) 仅UI截图转换为texture2d(适用于window端)

目录 需求 思路 1.截图并读取到本地 2.本地读取图片并转换为纹理2d 效果展示 找了好多的解决办法&#xff0c;都不管用。这个算是折中的。 需求 将当前的用户控件&#xff08;ui&#xff09;截图下来&#xff0c;并赋值到一个texture2d上。 我的需求&#xff1a;文字游戏…

matlab 三质量-弹簧系统受激振力

1、内容简介 略 44-可以交流、咨询、答疑 建立系统运动方程&#xff0c;研究固有频率和对应主振型 2、内容说明 略 三质量&#xff0d;弹簧系统受激振力&#xff0c;并不考虑各自的阻尼。建立系统运动方程。 解&#xff1a;由于阻尼对固有频率没有影响&#xff0c;故本文不…