@Test @Ignore public void performance() throws InterruptedException, ExecutionException { MultiKeySequentialExecutor<Integer> executor = new MultiKeySequentialExecutor<>(20); long now = System.currentTimeMillis(); long in5seconds = now + 3000; AtomicBoolean shutdown = new AtomicBoolean(false); AtomicBoolean done = new AtomicBoolean(false); Runnable task = () -> { while (System.currentTimeMillis() < in5seconds) { } if (done.get()) { System.err.println("AFTER DONE!"); } }; ExecutorService x = Executors.newFixedThreadPool(20); for (int i = 0; i < 1000_000; i++) { x.submit(() -> { executor.submit(ThreadLocalRandom.current().nextInt(0, 10), task); if (shutdown.get()) { System.err.println("After shutdown??"); } }); } x.shutdown(); x.awaitTermination(10_000, TimeUnit.MILLISECONDS); System.out.println("Shutdown = true"); shutdown.set(true); CompletableFuture[] completionFutures = IntStream.range(0, 10) .mapToObj(i -> executor.submit(i, task)) .toArray(CompletableFuture[]::new); CompletableFuture.allOf(completionFutures) .thenRun(() -> { done.set(true); System.err.println("Done after " + (System.currentTimeMillis() - in5seconds) + "ms"); }) .get(); Thread.sleep(1000); }
public CompletableFuture<Void> submit(K key, Runnable task) { return sequentialExecutors.computeIfAbsent(key, k -> new SequentialExecutor()) .submit(task); }
MultiKeySequentialExecutor { public CompletableFuture<Void> submit(K key, Runnable task) { return sequentialExecutors.computeIfAbsent(key, k -> new SequentialExecutor()) .submit(task); } }
MultiKeySequentialExecutor { public CompletableFuture<Void> submit(K key, Runnable task) { return sequentialExecutors.computeIfAbsent(key, k -> new SequentialExecutor()) .submit(task); } MultiKeySequentialExecutor(int nThreads);  MultiKeySequentialExecutor(ExecutorService executorService); }
MultiKeySequentialExecutor { public CompletableFuture<Void> submit(K key, Runnable task) { return sequentialExecutors.computeIfAbsent(key, k -> new SequentialExecutor()) .submit(task); } MultiKeySequentialExecutor(int nThreads);  MultiKeySequentialExecutor(ExecutorService executorService); CompletableFuture<Void> submit(K key, Runnable task); CompletableFuture<V> submit(K key, Supplier<V> task); void closeForKey(K key); SequentialExecutor getExecutorForKey(K key); }
MultiKeySequentialExecutor { public CompletableFuture<Void> submit(K key, Runnable task) { return sequentialExecutors.computeIfAbsent(key, k -> new SequentialExecutor()) .submit(task); } MultiKeySequentialExecutor(int nThreads);  MultiKeySequentialExecutor(ExecutorService executorService); CompletableFuture<Void> submit(K key, Runnable task); CompletableFuture<V> submit(K key, Supplier<V> task); void closeForKey(K key); SequentialExecutor getExecutorForKey(K key);  }