Multithreaded execution where order of finished Work Items is preserved

后端 未结 9 1215
无人共我
无人共我 2021-02-01 08:28

I have a flow of units of work, lets call them \"Work Items\" that are processed sequentially (for now). I\'d like to speed up processing by doing the work multithreaded.

<
9条回答
  •  花落未央
    2021-02-01 09:15

    Pump all your Futures through a BlockingQueue. Here's all the code you need:

    public class SequentialProcessor implements Consumer {
        private final ExecutorService executor = Executors.newCachedThreadPool();
        private final BlockingDeque> queue = new LinkedBlockingDeque<>();
    
        public SequentialProcessor(Consumer listener) {
            new Thread(() -> {
                while (true) {
                    try {
                        listener.accept(queue.take().get());
                    } catch (InterruptedException | ExecutionException e) {
                        // handle the exception however you want, perhaps just logging it
                    }
                }
            }).start();
        }
    
        public void accept(Task task) {
            queue.add(executor.submit(callableFromTask(task)));
        }
    
        private Callable callableFromTask(Task task) {
            return ; // implement this however
        }
    }
    

    Then to use, create a SequentialProcessor (once):

    SequentialProcessor processor = new SequentialProcessor(whatToDoWithResults);
    

    and pump tasks to it:

    Stream tasks; // given this
    
    tasks.forEach(processor); // simply this
    

    I created the callableFromTask() method for illustration, but you can dispense with it if getting a Result from a Task is simple by using a lambda instead or method reference instead.

    For example, if Task had a getResult() method, do this:

    queue.add(executor.submit(task::getResult));
    

    or if you need an expression (lambda):

    queue.add(executor.submit(() -> task.getValue() + "foo")); // or whatever
    

提交回复
热议问题