Alexander Collins
Alexander Collins

Reputation: 179

How can I create a thread pool in Java that does not run certain tasks concurrently?

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

Answers (2)

Alexei Kaigorodov
Alexei Kaigorodov

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

Bajrang Hudda
Bajrang Hudda

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

Related Questions