首页 文章

ExecutorService公平

提问于
浏览 1674
0

我有这样的ExecutorService

ExecutorService executor =  new ThreadPoolExecutor(threads, threads,
            0L, TimeUnit.MILLISECONDS,
            new ArrayBlockingQueue<>(1000, true));

我正在用.execute(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时,它工作正常

1 回答

  • 1

    你的LockManager似乎不对 . 您永远不会将这些锁放入 Map 中,因此您始终在同步新对象 .

    建议的变化:

    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;
    }
    

相关问题