@@ -23,7 +23,6 @@ of this software and associated documentation files (the "Software"), to deal
2323*/
2424package com .jano7 .executor ;
2525
26- import java .util .ArrayList ;
2726import java .util .HashMap ;
2827import java .util .LinkedList ;
2928import java .util .concurrent .Executor ;
@@ -33,18 +32,39 @@ public final class KeySequentialRunner<Key> {
3332
3433 private final class KeyRunner {
3534
36- private final LinkedList < Runnable > tasks = new LinkedList <>() ;
37- private boolean active = false ;
35+ private final Key key ;
36+ private LinkedList < Runnable > tasks ;
3837
39- public synchronized void run (Runnable task ) {
40- if (active ) {
41- tasks .addFirst (task );
42- } else {
43- active = true ;
38+ KeyRunner (Key key ) {
39+ this .key = key ;
40+ }
41+
42+ synchronized void run (Runnable task ) {
43+ if (tasks == null ) {
44+ tasks = new LinkedList <>();
4445 runTask (task );
46+ } else {
47+ tasks .add (task );
4548 }
4649 }
4750
51+ private synchronized Runnable pollTask () {
52+ return tasks .poll ();
53+ }
54+
55+ private Runnable nextTask () {
56+ Runnable runnable = pollTask ();
57+ if (runnable == null ) {
58+ synchronized (KeySequentialRunner .this ) {
59+ runnable = pollTask ();
60+ if (runnable == null ) {
61+ keyRunners .remove (key );
62+ }
63+ }
64+ }
65+ return runnable ;
66+ }
67+
4868 private void runTask (Runnable task ) {
4969 underlyingExecutor .execute (() -> {
5070 task .run ();
@@ -60,18 +80,6 @@ private void runTask(Runnable task) {
6080 }
6181 });
6282 }
63-
64- private synchronized Runnable nextTask () {
65- Runnable runnable = tasks .pollLast ();
66- if (runnable == null ) {
67- active = false ;
68- }
69- return runnable ;
70- }
71-
72- public synchronized boolean isActive () {
73- return active ;
74- }
7583 }
7684
7785 private final Executor underlyingExecutor ;
@@ -90,26 +98,12 @@ public KeySequentialRunner(Executor underlyingExecutor, TaskExceptionHandler exc
9098 }
9199
92100 public synchronized void run (Key key , Runnable task ) {
93- KeyRunner runner = keyRunners .get (key );
94- if (runner == null ) {
95- runner = new KeyRunner ();
96- keyRunners .put (key , runner );
97- }
98- runner .run (() -> {
101+ keyRunners .computeIfAbsent (key , KeyRunner ::new ).run (() -> {
99102 try {
100103 task .run ();
101104 } catch (Throwable t ) {
102105 exceptionHandler .handleTaskException (t );
103106 }
104107 });
105- scavengeInactiveRunners ();
106- }
107-
108- private void scavengeInactiveRunners () {
109- for (Key key : new ArrayList <>(keyRunners .keySet ())) {
110- if (!keyRunners .get (key ).isActive ()) {
111- keyRunners .remove (key );
112- }
113- }
114108 }
115109}
0 commit comments