我有像这样的ExecutorService
ExecutorService executor = new ThreadPoolExecutor(threads, threads,
0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(1000, true));
我正在使用.execute(Runnable)
向其发送作品我的runnable有
@Override
public void run() {
this.processor.performAction(this);
}
处理器有
public void performAction(RunnableAction action) {
Lock lock = lockManager.getLock(action.getId());
lock.lock();
try {
action.execute();
} finally {
lock.unlock();
}
}
其中lockManager是
public class LockManager {
Map<String, Lock> lockById = new HashMap<>(1000);
public synchronized Lock getLock(String id) {
Lock lock = lockById.get(id);
if (lock == null) {
lock = new ReentrantLock(true);
}
return lock;
}
并且我的actions / runnable有一个execQty字段,触发对某些命令的更新,调用它们的order.execute(execQty)
public void execute(int execQty) {
if (execQty < this.lastExecQty) {
System.err.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
System.err.println("id: " + this.id + " wrong order" + this.lastExecQty + " > " + execQty);
}
this.execQty += execQty;
this.lastExecQty = execQty;
}
}
我已经命令我的runnables发送到调度程序,每个qty字段都比前一个更大,所以在将每个runnable发送到ExecutorService之前打印我总是得到我需要的,有序的数字:
execute: id: 49 qty: 819
execute: id: 49 qty: 820
execute: id: 49 qty: 821
execute: id: 49 qty: 822
execute: id: 49 qty: 823
但即使我的ExecutorService由公平队列支持,并且我在每个实体更新之前使用每个实体锁,它仍然看起来实体没有按顺序更新
execute: id: 88 qty: 6
execute: id: 88 qty: 7
execute: id: 88 qty: 8
execute: id: 88 qty: 9
execute: id: 88 qty: 10
execute: id: 88 qty: 11
execute: id: 88 qty: 12
execute: id: 88 qty: 13
execute: id: 88 qty: 14
execute: id: 88 qty: 15
execute: id: 88 qty: 16
execute: id: 88 qty: 17
execute: id: 88 qty: 18
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
id: 88 wrong order 17 (previous) > 7 (current)
execute: id: 88 qty: 19
execute: id: 88 qty: 20
仅使用一个线程
运行ExecutorService时,它可以正常工作答案 0 :(得分:1)
你的LockManager看起来不对。您永远不会将这些锁放入地图中,因此您始终在同步新对象。
建议更改:
public synchronized Lock getLock(String id) {
Lock lock = lockById.get(id);
if (lock == null) {
lock = new ReentrantLock(true);
// put lock into the map so that next one will reuse it
lockById.put(id, lock);
}
return lock;
}