icp备案查看网站内容吗,室内设计相关网站,该企业为暂停开票企业解决方案,网站开发设计进度表1. JDK集合类
对于JDK的集合类#xff0c;forEach方法其实并不能完全避免并发修改异常。
forEach本质上还是一个循环遍历#xff0c;如果在循环体内直接对集合进行修改#xff0c;仍然会产生ConcurrentModificationException。
例如#xff1a;
ListString lis…1. JDK集合类
对于JDK的集合类forEach方法其实并不能完全避免并发修改异常。
forEach本质上还是一个循环遍历如果在循环体内直接对集合进行修改仍然会产生ConcurrentModificationException。
例如
ListString list new ArrayList();list.add(a);
list.add(b);list.forEach(item - {if(a.equals(item)){list.remove(item); // 会出错}
});这段代码在forEach中直接修改了list仍会抛出并发修改异常。
forEach之所以被认为能够避免并发修改异常主要有两个原因 使用外部变量暂存修改forEach只读不改 使用严格的函数式编程规范不修改外部状态
但实际上如果在forEach中直接修改集合问题仍然存在。
相比forEach,使用普通for循环甚至更好因为可以在修改前用实际大小预先拷贝一次集合。
所以forEach本质上不能避免并发修改异常需要通过保存修改至外部变量等方式进行规避。
更好的实践是 在修改前拷贝一次集合防止影响 使用stream流水线处理避免状态共享 外部保存修改forEach只读不改
2. Redisson
对于Redisson的RMap其forEach方法可以避免并发修改异常。
RMap的forEach方法使用了乐观锁的机制可以确保并发修改时的线程安全。
简单来说它的实现原理是 在forEach遍历时会获取一个乐观锁 如果在遍历过程中有其他线程修改了RMap,这会导致锁失效 一旦锁失效forEach会自动重新traverse重新获取新的锁 这样可以保证遍历过程中任何修改都不会导致并发异常
例如
RMapString, Integer map redisson.getMap(test);map.forEach((k, v) - {// 在foreach时删除或修改mapmap.remove(k);
}); 以上代码是安全的不会产生并发修改异常。
所以RMap的forEach方法通过乐观锁实现了对并发修改的安全遍历我们可以在forEach里面改变RMap而不用担心线程安全问题。
这是与JDK集合不同的一点对于Redis数据结构的遍历Redisson提供了更好的并发控制。 除了RMapRedisson还在其他数据结构提供了更优秀的并发控制机制 RLock - 红锁,基于Redis的分布式锁,确保线程安全RReadWriteLock - 读写锁,实现了自动扩展的锁RSemaphore - 信号量,基于Redis的语义RCountDownLatch - 分布式闭锁RSet - 并发Set,基于Redis的Set增强RQueue - 阻塞队列,可以监听元素事件RBlockingQueue - 带超时的阻塞队列RBlockingFairQueue - 公平阻塞队列RTopic - 发布订阅,支持集群RBatch - 支持异步批量命令 Redisson扩展了很多JDK并发工具类和集合接口基于Redis提供了分布式下的强一致性语义实现。
所以在分布式环境使用Redisson可以简化很多并发与同步的难点比如分布式锁、闭锁、信号量等。