Skip to content

Commit ec4f6e0

Browse files
committed
ThreadService: add ability to queue jobs flexibly
Previously, you could only queue a job to the special dispatch thread (typically the EDT). But in some scenarios, the EDT is exactly the wrong one to use. This commit adds the capability to queue jobs to any arbitrarily named queue. Essentially, each ID corresponds to a different single thread processing its jobs one at a time. This commit is dedicated to Hadrien Mary.
1 parent 35ee2f4 commit ec4f6e0

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

src/main/java/org/scijava/thread/DefaultThreadService.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333

3434
import java.awt.EventQueue;
3535
import java.lang.reflect.InvocationTargetException;
36+
import java.util.HashMap;
37+
import java.util.Map;
3638
import java.util.WeakHashMap;
3739
import java.util.concurrent.Callable;
3840
import 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());
@@ -147,6 +162,11 @@ public synchronized void dispose() {
147162
executor.shutdown();
148163
executor = null;
149164
}
165+
if (queues != null) {
166+
for (final ExecutorService queue : queues.values()) {
167+
queue.shutdown();
168+
}
169+
}
150170
}
151171

152172
// -- ThreadFactory methods --
@@ -164,6 +184,16 @@ private ExecutorService executor() {
164184
return executor;
165185
}
166186

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+
167197
private synchronized void initExecutor() {
168198
if (executor != null) return;
169199
executor = Executors.newCachedThreadPool(this);

src/main/java/org/scijava/thread/ThreadService.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,31 @@ void invoke(Runnable code) throws InterruptedException,
153153
*/
154154
void queue(Runnable code);
155155

156+
/**
157+
* Queues the given code for later execution in a dispatch thread associated
158+
* with the specified ID, returning immediately.
159+
*
160+
* @param id The ID designating which dispatch thread will execute the code.
161+
* @param code The code to execute.
162+
* @return A {@link Future} whose {@link Future#get()} method blocks until the
163+
* queued code has completed executing and returns {@code null}.
164+
* @see ExecutorService#submit(Runnable)
165+
*/
166+
Future<?> queue(String id, Runnable code);
167+
168+
/**
169+
* Queues the given code for later execution in a dispatch thread associated
170+
* with the specified ID, returning immediately.
171+
*
172+
* @param id The ID designating which dispatch thread will execute the code.
173+
* @param code The code to execute.
174+
* @return A {@link Future} whose {@link Future#get()} method blocks until the
175+
* queued code has completed executing and returns the result of the
176+
* execution.
177+
* @see ExecutorService#submit(Callable)
178+
*/
179+
<V> Future<V> queue(String id, Callable<V> code);
180+
156181
/**
157182
* Returns the thread that called the specified thread.
158183
* <p>

0 commit comments

Comments
 (0)