Closed. This question needs to be more focused。它当前不接受答案。
想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。
在8个月前关闭。
在以下情况下使用的正确结构是什么:
假设我们有一个库存系统(域并不真正重要,它只是一个示例),并且每个操作都很缓慢(例如,与外部系统联系)。
它可以处理约50个仓库(WH)。
我可以将库存从一个仓库转移到另一个仓库。
我想保证最终库存是正确的
我当时想的是,我可以并行处理不会影响相同WH的请求。例如:
将20个项目从WH 1移至3的请求
将15个项目从2移到5的请求(可以与上一个并行处理)
将5项从3移到6的请求到来(它应等待第一个请求完成后才能继续)。
我正在考虑一个线程安全的映射,其中包含我当前正在处理的所有仓库ID。
有更好的东西吗?
这样一来,您始终可以按照“正确”的顺序锁定两个仓库(例如,首先锁定较小的编号,然后锁定较高的编号;向后解锁)。这将确保您不会陷入僵局。
想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。
在8个月前关闭。
在以下情况下使用的正确结构是什么:
假设我们有一个库存系统(域并不真正重要,它只是一个示例),并且每个操作都很缓慢(例如,与外部系统联系)。
它可以处理约50个仓库(WH)。
我可以将库存从一个仓库转移到另一个仓库。
我想保证最终库存是正确的
我当时想的是,我可以并行处理不会影响相同WH的请求。例如:
将20个项目从WH 1移至3的请求
将15个项目从2移到5的请求(可以与上一个并行处理)
将5项从3移到6的请求到来(它应等待第一个请求完成后才能继续)。
我正在考虑一个线程安全的映射,其中包含我当前正在处理的所有仓库ID。
有更好的东西吗?
最佳答案
我建议您为每个lock
对象引入一个Warehouse
变量以及一个唯一的整数。您可以使用AtomicInteger
来确保每个创建的仓库都有唯一的编号
public class Warehouse {
private static final AtomicInteger numberProvider = new AtomicInteger(0);
private final int number;
private final Lock lock = new ReentrantLock();
// ...
public Warehouse(...) {
this.number = numberProvider.incrementAndGet();
...
}
// ... (getter for number and lock and other methods)
}
这样一来,您始终可以按照“正确”的顺序锁定两个仓库(例如,首先锁定较小的编号,然后锁定较高的编号;向后解锁)。这将确保您不会陷入僵局。
public void moveStock(Warehouse from, Warehouse to, int nof) {
List<Lock> locks = Stream.of(from, to)
.sorted(Comparator.comparingInt(Warehouse::getNumber))
.map(Warehouse::getLock)
.collect(Collectors.toList());
for(int i=0;i<locks.size();++i) {
locks.get(i).lock();
}
try {
from.substractStock(nof);
to.addStock(nof);
} finally {
for(int i=locks.size()-1;i>=0;i--) {
locks.get(i).unlock();
}
}
}
09-11 15:44