0% found this document useful (0 votes)
10 views2 pages

Java ExecutorCompletionService Example

The CompletionService interface allows batching multiple tasks together and polling for completed tasks. It combines a blocking queue with an executor. Tasks are submitted to the queue and then the queue can be polled, returning null if no task is completed or taking and blocking until a task is available. An example program demonstrates submitting 10 trivial tasks to an ExecutorCompletionService, waiting for them all to complete by polling the service and printing the results.

Uploaded by

jitendra99943
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views2 pages

Java ExecutorCompletionService Example

The CompletionService interface allows batching multiple tasks together and polling for completed tasks. It combines a blocking queue with an executor. Tasks are submitted to the queue and then the queue can be polled, returning null if no task is completed or taking and blocking until a task is available. An example program demonstrates submitting 10 trivial tasks to an ExecutorCompletionService, waiting for them all to complete by polling the service and printing the results.

Uploaded by

jitendra99943
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

CompletionService Interface

This lesson talks about how to batch multiple tasks together

CompletionService Interface

In the previous lesson we discussed how tasks can be submitted to


executors but imagine a scenario where you want to submit hundreds or
thousands of tasks. You'll retrieve the future objects returned from the
submit calls and then poll all of them in a loop to check which one is done
and then take appropriate action. Java offers a better way to address this
use case through the CompletionService interface. You can use the
ExecutorCompletionService as a concrete implementation of the interface.

The completion service is a combination of a blocking queue and an


executor. Tasks are submitted to the queue and then the queue can be
polled for completed tasks. The service exposes two methods, one poll
which returns null if no task is completed or none were submitted and
two take which blocks till a completed task is available.

Below is an example program that demonstrates the use of completion


service.

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

class Demonstration {

static Random random = new Random([Link]());

public static void main( String args[] ) throws Exception {


completionServiceExample();
}
static void completionServiceExample() throws Exception {

class TrivialTask implements Runnable {

int n;

public TrivialTask(int n) {
this.n = n;
}

public void run() {


try {
// sleep for one second
[Link]([Link](101));
[Link](n*n);
} catch (InterruptedException ie) {
// swallow exception
}
}
}

ExecutorService threadPool = [Link](3);


ExecutorCompletionService<Integer> service =
new ExecutorCompletionService<Integer>(threadPool);

// Submit 10 trivial tasks.


for (int i = 0; i < 10; i++) {
[Link](new TrivialTask(i), new Integer(i));
}

// wait for all tasks to get done


int count = 10;
while (count != 0) {
Future<Integer> f = [Link]();
if (f != null) {
[Link]("Thread" + [Link]() + " got done.");
count--;
}
}

[Link]();
}

Common questions

Powered by AI

In the example of task execution using ExecutorCompletionService provided in Source 1, a fixed-size thread pool of 3 threads is created to manage the execution of tasks. Trivial tasks, which calculate the square of a number, are submitted to the service. The ExecutorCompletionService manages these tasks by submitting them to the thread pool for execution. As each task completes, the service adds it to a queue, allowing the main program to poll for completed tasks, retrieving and printing the results. This example demonstrates the efficiency of collecting and processing results from multiple asynchronous tasks without manually managing their completion .

The ExecutorCompletionService is a concrete implementation of the CompletionService interface, combining an Executor and a blocking queue. It is particularly useful in a multi-threaded environment where numerous tasks are submitted for execution. By utilizing an ExecutorCompletionService, developers can submit tasks for execution and efficiently manage their completion status. This is achieved through its method of queuing completed tasks, allowing the retrieval of results using 'poll' or 'take' methods. In a multi-threaded environment, this means that the overhead of manually managing task completion is reduced, leading to more streamlined code and improved performance .

ExecutorCompletionService handles task result retrieval by queuing completed tasks and allowing the user to access results through 'poll' or 'take' methods. This method of handling results allows a program to continue executing other tasks or processing those that are completed, rather than stalling due to uncompleted tasks. As a result, program efficiency is increased due to the availability of results in real-time and the ability to handle them as soon as they are ready, minimizing idle times and improving throughput .

The CompletionService interface improves task execution by combining the functionalities of a blocking queue and an executor, allowing for better management of task completion. Instead of manually polling future objects from submit calls to determine which tasks are completed, the CompletionService automatically manages this by queuing the completed tasks. This allows developers to use the 'poll' method to non-blockingly check for completed tasks or the 'take' method to block until a task is done. This results in more efficient and clean code for handling a large number of tasks .

The CompletionService interface provides two primary methods: 'poll' and 'take'. The 'poll' method is used to check for completed tasks without blocking, returning null if no tasks are completed. Conversely, the 'take' method blocks the execution until a task is completed and available, thus providing a way to handle tasks as they finish in real-time .

While the CompletionService interface does not directly support task prioritization, it can be implemented through workarounds. One approach is to encapsulate tasks within a wrapper that implements the Comparable interface, allowing them to be ordered before submission. Alternatively, multiple ExecutorCompletionServices with priority-based Executor instances could manage tasks with different priorities. These approaches allow the separation and ordered execution of priority-based tasks, achieving task execution in order of importance based on custom criteria defined within the encapsulation .

The ExecutorCompletionService provides several advantages over traditional executor services when handling bulk task submissions. Chief among these is its ability to automatically manage and queue completed tasks, which simplifies the retrieval process. Unlike traditional executors where future objects must be managed manually, the CompletionService allows easy access to completed task results either via non-blocking polling or blocking until a task is available. This reduces the complexity and overhead required to monitor and process tasks, especially when dealing with large volumes .

Using a fixed-size thread pool with the CompletionService interface can lead to potential issues such as resource exhaustion and task starvation if the number of tasks significantly exceeds the size of the pool. Mitigation can be achieved by properly sizing the thread pool based on the expected task load and performance considerations. Additionally, task prioritization or task grouping can help manage the queue efficiently. Developers should also consider monitoring thread usage and adjusting the pool size as necessary to accommodate changing workloads or to maintain optimal performance .

Blocking operations in the CompletionService interface affect program flow by pausing execution until a task is completed. This can prevent the program from continuing other operations if it is waiting for a specific task result. However, in scenarios where task results are needed before proceeding with subsequent operations, blocking can be preferred as it ensures that required data or state is available. This is particularly useful in dependency chains or when dealing with critical tasks that must be completed to maintain consistency or correct sequence in program operations .

Thread management with the CompletionService interface is optimized through the use of a pooled thread executor, specifically the ExecutorCompletionService. This interface allows tasks to be efficiently queued and executed using a predefined number of threads. By limiting concurrency to a certain number of threads, resource usage is optimized, preventing excessive thread creation that could lead to performance bottlenecks. The CompletionService handles the queuing of finished tasks, ensuring that they can be processed as soon as a thread becomes available. This method improves upon manual threading implementations by reducing complexity and enhancing performance through better resource management .

You might also like