Last active
December 14, 2015 07:08
-
-
Save wytten/5048011 to your computer and use it in GitHub Desktop.
Submit a number of tasks to be executed by a fixed-size thread pool, then be informed as each task is completed. Exit
when all are complete.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*.class | |
*~ | |
.project |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Random; | |
import java.util.concurrent.Callable; | |
import java.util.concurrent.CompletionService; | |
import java.util.concurrent.ExecutionException; | |
import java.util.concurrent.ExecutorCompletionService; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.Future; | |
/** | |
* Demonstration of {@link java.util.concurrent} thread pooling capability.<br/> | |
* Submits a number of tasks to be executed by a fixed-size thread pool, then is informed as each task is completed.<br/> | |
* Exits when all are complete. | |
*/ | |
public class CompletionServiceApp { | |
private static final int NUM_TASKS = 100; | |
private static final int NUM_THREADS = 4; | |
private static final ExecutorService POOL = Executors.newFixedThreadPool(NUM_THREADS); | |
private static final CompletionService<String> SERVICE = new ExecutorCompletionService<String>(POOL); | |
private static final Random RANDOM = new Random(System.currentTimeMillis()); | |
public static void main(String[] args) throws InterruptedException, ExecutionException { | |
// submit the tasks | |
for (int i = 1; i <= NUM_TASKS; i++) { | |
SERVICE.submit(new StringTask(i)); | |
} | |
// await their completion | |
int completedCount = 0; | |
while (completedCount < NUM_TASKS) { | |
// obtain the next completed result holder | |
Future<String> future = SERVICE.take(); | |
assert future.isDone(); | |
// get the result returned by the task's call() method | |
String result = future.get(); | |
if (result == null) { | |
System.err.println("Failure detected"); | |
continue; | |
} | |
// task completed; print the result | |
System.out.println(result); | |
completedCount++; | |
} | |
POOL.shutdown(); | |
} | |
public static class StringTask implements Callable<String> { | |
private static final int MAX_DELAY = 1000; | |
private int taskNumber; | |
public StringTask(int taskNumber) { | |
this.taskNumber = taskNumber; | |
} | |
@Override | |
public String call() throws Exception { | |
// random delay, simulating work being performed | |
long delay = 1 + Math.abs(RANDOM.nextLong() % MAX_DELAY); | |
Thread.sleep(delay); | |
// randomly introduce simulated failures | |
if (RANDOM.nextDouble() > 0.9) { | |
System.err.println("Simulated failure!"); | |
// One might throw an Exception here (which would get wrapped in a ExecutionException) | |
// but unfortunately there is no easy way for the caller to know which particular task | |
// threw the exception. So taking the awkward step of having this task resubmit itself | |
// here, rather than have the caller do it, as one might expect. | |
SERVICE.submit(this); | |
return null; | |
} | |
return String.format("Task #%d slept for %dms serviced by thread %s", taskNumber, delay, Thread.currentThread() | |
.getName()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment