3333
3434import java .awt .EventQueue ;
3535import java .lang .reflect .InvocationTargetException ;
36+ import java .util .HashMap ;
37+ import java .util .Map ;
3638import java .util .WeakHashMap ;
3739import java .util .concurrent .Callable ;
3840import java .util .concurrent .ExecutorService ;
@@ -65,6 +67,9 @@ public final class DefaultThreadService extends AbstractService implements
6567
6668 private ExecutorService executor ;
6769
70+ /** Mapping from ID to single-thread {@link ExecutorService} queue. */
71+ private Map <String , ExecutorService > queues ;
72+
6873 private int nextThread = 0 ;
6974
7075 private boolean disposed ;
@@ -117,6 +122,16 @@ public void queue(final Runnable code) {
117122 EventQueue .invokeLater (wrap (code ));
118123 }
119124
125+ @ Override
126+ public Future <?> queue (final String id , final Runnable code ) {
127+ return executor (id ).submit (wrap (code ));
128+ }
129+
130+ @ Override
131+ public <V > Future <V > queue (final String id , final Callable <V > code ) {
132+ return executor (id ).submit (wrap (code ));
133+ }
134+
120135 @ Override
121136 public Thread getParent (final Thread thread ) {
122137 return parents .get (thread != null ? thread : Thread .currentThread ());
@@ -141,9 +156,17 @@ public ThreadContext getThreadContext(final Thread thread) {
141156 // -- Disposable methods --
142157
143158 @ Override
144- public void dispose () {
159+ public synchronized void dispose () {
145160 disposed = true ;
146- if (executor != null ) executor .shutdown ();
161+ if (executor != null ) {
162+ executor .shutdown ();
163+ executor = null ;
164+ }
165+ if (queues != null ) {
166+ for (final ExecutorService queue : queues .values ()) {
167+ queue .shutdown ();
168+ }
169+ }
147170 }
148171
149172 // -- ThreadFactory methods --
@@ -157,12 +180,25 @@ public Thread newThread(final Runnable r) {
157180 // -- Helper methods --
158181
159182 private ExecutorService executor () {
160- if (executor == null ) {
161- executor = Executors .newCachedThreadPool (this );
162- }
183+ if (executor == null ) initExecutor ();
163184 return executor ;
164185 }
165186
187+ private synchronized ExecutorService executor (final String id ) {
188+ if (disposed ) return null ;
189+ if (queues == null ) queues = new HashMap <>();
190+ if (!queues .containsKey (id )) {
191+ final ExecutorService queue = Executors .newSingleThreadExecutor ();
192+ queues .put (id , queue );
193+ }
194+ return queues .get (id );
195+ }
196+
197+ private synchronized void initExecutor () {
198+ if (executor != null ) return ;
199+ executor = Executors .newCachedThreadPool (this );
200+ }
201+
166202 private Runnable wrap (final Runnable r ) {
167203 final Thread parent = Thread .currentThread ();
168204 return new Runnable () {
0 commit comments