Reputation: 179
I'd like to submit tasks to a thread pool (or executor service) but task should not be executed concurrently if there's already one task in the executor with the same key.
Specifically, this is for a build tool, to prevent tasks for the same part of a source tree executing concurrently.
This is an example of why I would want this behaviour:
public class Example {
public static void main(String[] args) throws Exception {
ExecutorService service = Executors.newFixedThreadPool(2);
Path resource = Paths.get("tmp");
service.submit(() -> {
Files.write(resource, Collections.singleton("foo"));
Thread.sleep(10);
if (!new String(Files.readAllBytes(resource)).equals("foo")) {
System.err.println("someone changed my stuff");
}
return null;
});
service.submit(() -> Files.write(resource, Collections.singleton("bar")));
service.shutdown();
service.awaitTermination(1, TimeUnit.MINUTES);
}
}
Upvotes: 0
Views: 304
Reputation: 13535
The solution is to use a separate single-threaded executor for each key. Since there can exist many keys, creating a thread for each key can be expensive, and so we replace single-threaded executor with a light-weight SerialExecutor
which behaves like a single-threaded executor but have no own thread, borrowing a thread from some normal backend executor when needed. SerialExecutor
is described in JavaDocs of Executor. Opimized version can be found at my CodeSamples project,
See similar question Design pattern to guarantee only one Runnable object of particular id value is being executed by the pool
Upvotes: 1
Reputation: 3288
Try with 2 different executers for your different type of tasks and if first pool completed then start another one.
ExecutorService executor1 = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new FirstTask("" + i);
executor1.execute(worker);
}
executor1.shutdown();
while (!executor.isTerminated()) {
}
ExecutorService executor2 = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new AnotherTask("" + i);
executor2.execute(worker);
}
executor2.shutdown();
Upvotes: 0