Controlling Task execution order with ExecutorService

前端 未结 8 1950
一生所求
一生所求 2020-12-02 14:30

I have a process which delegates asynch tasks to a pool of threads. I need to ensure that certain tasks are executed in order. So for example

Tasks arrive in order<

8条回答
  •  离开以前
    2020-12-02 15:09

    I write own Executor that warrants task ordering for tasks with same key. It uses map of queues for order tasks with same key. Each keyed task execute next task with the same key.

    This solution don't handle RejectedExecutionException or other exceptions from delegated Executor! So delegated Executor should be "unlimited".

    import java.util.HashMap;
    import java.util.LinkedList;
    import java.util.Map;
    import java.util.Queue;
    import java.util.concurrent.Executor;
    
    /**
    * This Executor warrants task ordering for tasks with same key (key have to implement hashCode and equal methods correctly).
    */
    public class OrderingExecutor implements Executor{
    
        private final Executor delegate;
        private final Map> keyedTasks = new HashMap>();
    
        public OrderingExecutor(Executor delegate){
            this.delegate = delegate;
        }
    
        @Override
        public void execute(Runnable task) {
            // task without key can be executed immediately
            delegate.execute(task);
        }
    
        public void execute(Runnable task, Object key) {
            if (key == null){ // if key is null, execute without ordering
                execute(task);
                return;
            }
    
            boolean first;
            Runnable wrappedTask;
            synchronized (keyedTasks){
                Queue dependencyQueue = keyedTasks.get(key);
                first = (dependencyQueue == null);
                if (dependencyQueue == null){
                    dependencyQueue = new LinkedList();
                    keyedTasks.put(key, dependencyQueue);
                }
    
                wrappedTask = wrap(task, dependencyQueue, key);
                if (!first)
                    dependencyQueue.add(wrappedTask);
            }
    
            // execute method can block, call it outside synchronize block
            if (first)
                delegate.execute(wrappedTask);
    
        }
    
        private Runnable wrap(Runnable task, Queue dependencyQueue, Object key) {
            return new OrderedTask(task, dependencyQueue, key);
        }
    
        class OrderedTask implements Runnable{
    
            private final Queue dependencyQueue;
            private final Runnable task;
            private final Object key;
    
            public OrderedTask(Runnable task, Queue dependencyQueue, Object key) {
                this.task = task;
                this.dependencyQueue = dependencyQueue;
                this.key = key;
            }
    
            @Override
            public void run() {
                try{
                    task.run();
                } finally {
                    Runnable nextTask = null;
                    synchronized (keyedTasks){
                        if (dependencyQueue.isEmpty()){
                            keyedTasks.remove(key);
                        }else{
                            nextTask = dependencyQueue.poll();
                        }
                    }
                    if (nextTask!=null)
                        delegate.execute(nextTask);
                }
            }
        }
    }
    

提交回复
热议问题