randomaccessfile分片读取必须手动计算offset和length,多线程需各自独立实例、严格按字节区间划分并显式处理余数,合并时seek写入必须对齐且避免覆盖。

RandomAccessFile 分片读取必须手动计算 offset 和 length
直接用 RandomAccessFile 多线程读文件,不会自动帮你切位置 —— 每个线程得知道自己该从哪读、读多少。常见错误是让所有线程都从 0 开始读,或用 file.length() / threadCount 简单均分却忽略余数,导致最后几字节丢失、文件损坏。
正确做法是:按字节边界划分,每个线程负责一段连续区间,例如 4 线程处理 10MB 文件,则线程 0 读 [0, 2500000),线程 1 读 [2500000, 5000000),以此类推;最后一段要显式算出 end = Math.min(start + chunkSize, file.length())。
- 切片前先调用
file.length()获取真实大小,不能依赖文件系统缓存 - 每个线程创建独立的
RandomAccessFile实例(不要共享),避免seek()冲突和指针错位 - 读取时用
read(byte[], off, len)批量读,别用read()单字节循环,性能差且易出错
合并时 seek 写入必须严格对齐 chunkIndex × chunkSize
多线程写入合并文件最常崩在「覆盖写」或「错位写」:比如两个线程同时往同一个 RandomAccessFile 实例写,或一个线程 seek(1024) 后还没写完,另一个线程又 seek(1024) 覆盖了前半部分。
安全做法是:合并目标文件只开一个 RandomAccessFile("target", "rw"),每个线程拿到自己的写入偏移后,先 seek(pos),再 write(),且不加锁也必须保证 pos 不重叠 —— 这就要求分片逻辑和合并逻辑使用完全一致的切块公式。
对设计或页面进行 WCAG 2.1 AA 无障碍审计。触发关键词:“audit accessibility”、 “check a11y”、 “is this accessible?” 或在审查设计时使用。
- 写入前务必检查目标文件是否已存在且可写,否则
FileNotFoundException或AccessDeniedException - 不要在写入中途调用
getFilePointer()判断位置,它返回的是当前指针,不是你期望的写入点 - 若需断点续传,得额外记录每个分片的
chunkIndex和完成状态,靠外部存储(如 Redis 或临时文件)协调
ThreadPoolExecutor 线程数 ≠ 文件分片数,但必须匹配
代码里常见硬编码 new ThreadPoolExecutor(n, n+1, ...),看似分配了 n 个线程对应 n 个分片,但实际运行中如果 n 超过 CPU 核心数太多,IO 等待反而加剧,吞吐不升反降。
合理设置应基于:文件大小、磁盘类型(SSD vs HDD)、JVM 堆内存。例如 10GB 文件在 SATA SSD 上,并发 8–16 线程较稳;若在机械盘上,4–8 更合适;超过 32 线程基本无收益,还可能触发 GC 压力。
- 拒绝策略别用
AbortPolicy,建议CallerRunsPolicy让主线程兜底,避免任务丢失 - 队列用
ArrayBlockingQueue比LinkedBlockingQueue更可控,容量设为分片总数即可 - 线程空闲时间不宜设太短(如
1L秒),否则频繁销毁重建线程,开销反超收益
CompletableFuture 并行合并比裸线程更易控错和收口
用原始 Thread + CountDownLatch 做同步,一旦某个线程抛异常,latch.await() 可能永远卡住,或者异常被吞掉无法定位。
改用 CompletableFuture 就清晰得多:每个分片读取封装成一个 CompletableFuture<byte></byte>,用 CompletableFuture.allOf() 等全部完成,再统一收集结果或捕获异常堆栈。
- 合并阶段若需顺序写入,仍得用单个
RandomAccessFile,但读取阶段可彻底并行化 -
thenAcceptAsync()不要默认用公共 ForkJoinPool,应传入自定义线程池,避免干扰其他异步任务 - 大文件场景下慎用
join()阻塞等待,可用orTimeout()加超时保护,防某分片卡死拖垮整体
seek() 的毫秒级延迟、write() 的部分成功、线程调度的不可预测性,都会在最终合并文件里留下细微但致命的 corruption。这些细节,往往只在压测或线上真实大文件场景里才暴露。










