continue本身不实现并发过滤,仅在检测到分片已被处理(如通过AtomicBoolean数组或ConcurrentHashMap判别)后跳过当前迭代;真正起作用的是配合共享状态的原子判断逻辑。

在多线程分片统计任务中,continue 本身不能直接“过滤掉已被其他线程处理的分片”,它只是跳过当前循环迭代;真正起作用的是**配合共享状态(如原子标记、并发集合或分布式锁)的判断逻辑**。把 continue 放在“发现本分片已被处理”的检查之后,才能实现跳过——它是个执行层面的配合动作,不是并发控制机制。
用原子布尔数组标记分片状态
适用于单机多线程、分片总数固定且可预知(如 0~999)的场景。预先创建 AtomicBoolean[] processed = new AtomicBoolean[n],每个分片对应一个位置。
- 线程拿到分片编号
i后,先调用processed[i].compareAndSet(false, true) - 若返回
false,说明已被其他线程抢先设为true,此时用continue跳过该分片 - 若返回
true,说明抢到了,继续执行统计逻辑
用 ConcurrentHashMap 做去重登记
适合分片标识不可预编号(如字符串 ID、复合键)或动态生成的场景。
- 声明
ConcurrentHashMapclaimed = new ConcurrentHashMap() - 对每个分片 key(如
"shard_20240515_user"),调用claimed.putIfAbsent(key, true) == null - 若为
false,表示已存在,执行continue - 注意:不要用
containsKey+put,那是非原子的,会导致重复处理
避免常见陷阱
不能只靠本地变量或普通 boolean 数组:多个线程看到的值不同步,continue 会失效。
不要在锁外判断、锁内处理再 continue:加锁前就可能已被处理,白白阻塞;应尽量用无锁原子操作快速判别。
处理失败后需回滚标记:如果统计中途异常,记得调用 processed[i].set(false) 或 claimed.remove(key),否则该分片永久丢失。
补充:分布式环境怎么办?
单机方案失效时,需借助外部协调服务:
- Redis:用 SET key value NX EX 30 尝试占位,失败则 continue
- ZooKeeper:创建临时顺序节点,只让序号最小者处理,其余 continue
- 数据库唯一约束:INSERT 分片处理记录(带唯一索引),捕获唯一冲突异常后 continue










