多Vessel代理同时检索Collection引发存储移除错误的解决问询
解决多Vessel代理重复移除集合容器的问题
你遇到的错误根源是多艘Vessel并发访问StoredContainers集合时,多个代理同时执行移除操作,导致重复获取并尝试移除同一个容器对象,进而引发冲突。以下是几种可行的解决方法:
用同步块控制并发访问
在集合操作代码外层添加synchronized块,强制同一时间仅允许一个Vessel修改集合:synchronized(StoredContainers) { int nContainers = Math.min(agent.Capacity, StoredContainers.size()); for (int i = 0; i < nContainers; i++) { Container c = StoredContainers.remove(StoredContainers.size() - 1); loadingProcess0.PrepareLoading1.take(c); } }这种方式实现简单,适合集合操作频率较低的场景。
改用线程安全的集合类
将StoredContainers替换为Java内置的线程安全集合,比如支持高效尾部移除的ConcurrentLinkedDeque:- 定义集合时:
ConcurrentLinkedDeque<Container> StoredContainers = new ConcurrentLinkedDeque<>(); - 移除容器时使用线程安全的
pollLast()方法,并增加空值判断(避免并发下集合大小变化导致返回null):int nContainers = Math.min(agent.Capacity, StoredContainers.size()); for (int i = 0; i < nContainers; i++) { Container c = StoredContainers.pollLast(); if(c != null) { loadingProcess0.PrepareLoading1.take(c); } }
线程安全集合内置并发控制逻辑,无需手动加锁,适合高并发场景。
- 定义集合时:
使用信号量限制访问数量
通过Semaphore信号量控制同时访问集合的Vessel数量,确保同一时间仅一个代理执行装载操作:- 在模型中创建信号量对象(初始许可数设为1):
Semaphore storageLock = new Semaphore(1); - 在取容器的代码中调用信号量:
try { storageLock.acquire(); int nContainers = Math.min(agent.Capacity, StoredContainers.size()); for (int i = 0; i < nContainers; i++) { Container c = StoredContainers.remove(StoredContainers.size() - 1); loadingProcess0.PrepareLoading1.take(c); } } catch(InterruptedException e) { e.printStackTrace(); } finally { storageLock.release(); }
这种方式灵活性更高,可根据业务需求调整允许并发的Vessel数量。
- 在模型中创建信号量对象(初始许可数设为1):
内容的提问来源于stack exchange,提问作者Scar
相关产品推荐
相关产品推荐

