Zhaixx's Blog

Zhaixx's Blog

JUC-CompleteFuture总结
发表于2025-03-18|JUC
CompletableFuture 完全指南 从 Runnable 到 CompletableFuture,全面理解 Java 并发异步编排。 前言在日常开发中,我们经常会遇到需要开启子线程执行任务的场景,比如网络请求、数据库操作、复杂计算等等。Java 为我们提供了多种方式来实现异步操作,从最基础的 Runnable、Callable 到 Future,但这些传统方式在实际使用中存在很多局限,尤其是在面对复杂的异步回调、异常处理、任务组合时。本文将带你从最基础的线程模型讲起,一步步剖析为什么 CompletableFuture 会诞生,它到底帮我们解决了哪些问题,以及如何用它优雅地实现高效的异步编排。 目录 2. Runnable、Callable 与 Future:基础异步模型 2.1 Runnable 简介 2.2 Callable 与 Future 简介 2.3 Runnable & Callable & Future 的局限 3. CompletableFuture 为什么出现? 4. CompletableFuture 核心用法 4.1...
SQL性能分析
发表于2025-02-20|MySQL
SQL性能分析(MySQL)SQL执行频次查询MySQL客户端连接成功后,通过show[session | global] status命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次: 1SHOW GLOBAL STATUS LIKE...
为什么InnoDb采用B+树索引而不是B树或者Hash
发表于2025-02-20
为什么 InnoDB 选择 B+ 树索引,而不是 B 树或者 Hash?InnoDB 选择 B+ 树(B+Tree)索引 作为默认存储引擎索引结构,主要是因为它 兼顾查询效率、范围查询、磁盘存取优化,而 B 树 和 哈希索引(Hash) 各有局限性。 1. B+ 树 vs B 树 特性 B+ 树(B+Tree) B 树(B-Tree) 数据存储位置 仅叶子节点存储数据 所有节点(包括内部节点)都存储数据 范围查询(BETWEEN, >, <) ✅ 高效(叶子节点链表结构) ❌ 低效(必须遍历整个树) 磁盘读取效率 ✅ 更少的磁盘 I/O,更快的查询 ❌ 节点大小不均,I/O 开销大 索引扫描(ORDER BY) ✅ 高效支持 ❌ 不支持,查询需回溯树结构 🔹 为什么 B+ 树更适合数据库? 范围查询更高效: B+ 树的 叶子节点 通过 链表连接,遍历时可以 直接顺序访问,适合 BETWEEN、ORDER BY、LIKE 'prefix%' 查询。 B...
Mysql事务和存储引擎
发表于2025-02-18|Mysql
事务ACID Atomicity Consistency Isolation Durability 并发事务问题 脏读 一个事务读到另外一个事务还没有提交的数据 不可重复读 一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复度,也就是一个事务第一次和第二次读的中间这个数据被另一个事务提交修改了,所以不一致 幻读 查询的时候没有,插入的时候出现了,跟不可重复读差不多,不过是从0到1。 MySQL 事务隔离级别 隔离级别 脏读 不可重复读 幻读 描述 读未提交 (Read Uncommitted) ✅ ✅ ✅ 允许读取未提交的数据,可能导致脏读、不可重复读和幻读。 读已提交 (Read Committed) ❌ ✅ ✅ 只能读取已提交数据,避免了脏读,但仍可能发生不可重复读和幻读。 可重复读 (Repeatable Read) ❌ ❌ ✅ 确保同一事务中多次读取数据一致,防止脏读和不可重复读,但可能出现幻读。 串行化...
S6.081 fs解析
发表于2024-12-23|S6.081 lab解析
Large files这个lab的任务是增加xv6文件的最大大小,目前一个Inode里有12个直接块号和1个间接块号,总共12 + 256 = 268个块,我们需要修改Inode(将一个直接块变为二级索引块)使得一个文件能够变得更大,具体的步骤是先修改fs.h中NDIRECT的定义,然后再去修改bmap使得操作系统能够访问到我们增加的块 具体实现修改宏定义12345// fs.h#define NDIRECT 11uint addrs[NDIRECT+2]; // Data block addresses//file.huint addrs[NDIRECT+2]; 修改bmap12345678910111213141516171819202122232425bn -= NINDIRECT; if (bn < NINDIRECT * NINDIRECT) { if ((addr = ip->addrs[NDIRECT + 1]) == 0) { ip->addrs[NDIRECT + 1] =...
S6.081 Locks解析
发表于2024-12-23|S6.081 lab解析
LocksMemory allocktor(moderate)kalloc中多个cpu进行并发时会产生锁争用,我们要对每一个cpu维护一下freelist来优化,减少锁征用具体做法是一开始将所有的可用内存分配给一个cpu,然后其他cpu在没有可用内存时可以从其他cpu那里偷一些内存,然后谁释放的内存这个内存就归谁。 修改kmem1234struct { struct spinlock lock; struct run *freelist;} kmem[NCPU]; 修改kinit,给每个cpu分配一个kmem,并初始化自旋锁1234567891011voidkinit(){ char buffer[100]; for(int i = 0;i < NCPU;i++){ snprintf(buffer, 100, "kmem%d", i); initlock(&kmem[i].lock, buffer);; } // initlock(&kmem.lock,...
io-uring学习总结
发表于2024-12-22|Tokio
这两天学了一些关于io-uring的内容,但是要理解io-uring的性能为什么快,我觉得应该先了解传统的IO多路复用,也就是Select、Poll以及Epoll,然后才能明白为什么Io-uring比较快。 IO的基本流程传统IO的基本流程一般都是应用程序也就是用户态下的代码发起IO请求,然后发生系统调用,系统由用户态转移到内核态,内核进行IO操作,得到结果之后把内容拷贝进用户空间,这里的开销主要在于上下文切换和IO本身的开销,因为IO相对于cpu运行的速度来说是非常慢的,而且磁盘运行速度也远低于内存,我们为了等待io就会浪费大量的cpu资源,因此出现了IO模型 IO模型的种类在Linux下一般有如下五种IO模型 blocking I/O nonblocking I/O I/O multiplexing (select 、poll、 epoll) signal driven I/O (SIGIO) asynchronous I/O (the POSIX aio_functions)下面我们逐一介绍 blocking...
Tokio-Schedule阅读
发表于2024-12-13|Tokio
Multi-threads因为默认的配置是多线程的,所以先阅读的多线程的部分 mod.rs这里主要是关于 Schedule 的 Handle 以及调度 worker 运行时的 Context,他们都通过 enum 进行了一层抽象,就是里面都是差不多的内容,不过外面包了一层枚举类型,你可以通过这个类型来找到当前的 Runtime 是多线程还是单线程的,接下来是 Handle 和 Context 具体的内容 123456789101112131415161718192021222324252627pub(crate) struct Handle { /// Task spawner pub(super) shared: worker::Shared, /// Resource driver handles pub(crate) driver: driver::Handle, /// Blocking pool spawner pub(crate) blocking_spawner: blocking::Spawner, ///...
S6.081 lab解析
发表于2024-12-12|S6.081 lab解析
MultithreadingUthread:switching between threads    这个实验是在给定的代码基础上实现用户级的线程切换,我们只需要模仿一下 Kernel 中的 Context 即可(1)定义一下 context 12345678910111213141516struct context { uint64 ra; uint64 sp; uint64 s0; uint64 s1; uint64 s2; uint64 s3; uint64 s4; uint64 s5; uint64 s6; uint64 s7; uint64 s8; uint64 s9; uint64 s10; uint64 s11;}; (2)修改一下 thread 结构体 12345struct thread { char stack[STACK_SIZE]; /* the thread's stack */ int state; ...
Tokio-Task阅读
发表于2024-12-10|Tokio
任务模块概述任务模块负责管理运行时生成的任务,并为其他模块提供安全的 API 接口。每个任务通常存储在 OwnedTasks 或 LocalOwnedTasks 中,并通过引用计数(ref-count)来跟踪任务的活动引用。 任务引用类型在运行时,任务可以通过不同的引用类型进行管理,主要有以下几种: **OwnedTask**:任务存储在 OwnedTasks 或 LocalOwnedTasks 中。 **JoinHandle**:任务的句柄,允许访问任务的输出。 **Waker**:每个任务可以有多个 Waker 引用,用于唤醒任务继续执行。 **Notified**:用于追踪任务是否被通知。 **Unowned**:用于任务不在运行时管理下的引用,通常用于阻塞任务或测试。 Unowned 类型会占用两个引用计数,而其他引用类型只占用一个,Unowned 通过std::mem::forget函数保证了两个引用计数 任务状态任务的状态通过一个原子 usize...
123
avatar
Zhaixx
文章
21
标签
0
分类
6
Follow Me
公告
This is my Blog
最新文章
6.824ShardKV实现2025-08-15
6.824-实现 raft_kv2025-07-30
raft实现2025-07-18
TCP Receiver Sender实现2025-07-14
Google File System设计阅读2025-05-23
分类
  • 6.824分布式系统6
  • JUC3
  • MySQL1
  • Mysql1
  • S6.081 lab解析3
  • Tokio4
归档
  • 八月 2025 1
  • 七月 2025 3
  • 五月 2025 4
  • 三月 2025 3
  • 二月 2025 3
  • 十二月 2024 7
网站信息
文章数目 :
21
本站访客数 :
本站总浏览量 :
最后更新时间 :
©2024 - 2025 By Zhaixx
框架 Hexo|主题 Butterfly
Hi, welcome to my blog!