JDK Documentation Description:
Public Interface Completionservice<v>
A service that separates the production of new asynchronous tasks from the results of using the completed tasks. The task that the producer submit to perform. The consumer take the completed tasks and process their results in the order in which they were completed. For example, Completionservice can be used to manage asynchronous IO, the task of performing a read operation is committed as part of a program or system, and then, when the read operation is completed, other actions are performed in different parts of the program, and the Order of operations may differ from the order in which they were requested. Typically, Completionservice relies on a single Executor to actually perform tasks, in which case Completionservice only manages an internal completion queue. The Executorcompletionservice class provides an implementation of this method. Memory consistency effect: The action happen-before the task performed before the task is submitted to Completionservicein the thread, which in turn happen-before immediately after the action returned from the corresponding take ()
All known implementation classes:
Description of the JDK for the subclass:
Public class Executorcompletionservice<v>extends objectimplements completionservice<v> using the provided Executor To perform the completionservice of the task. This class arranges the tasks that are submitted when they are completed, placing them on a queue that can be accessed using take. This class is very lightweight and is suitable for temporary use when performing several sets of tasks.
All the methods:
| Method Summary |
Future<V> |
poll() Gets and removes the future that represents the next completed task, and returns nullif no such task exists. |
Future<V> |
poll(long timeout, TimeUnit unit) Gets and removes the future that represents the next completed task, and if such a task does not currently exist, waits for the specified time, if necessary. |
Future<V> |
submit(Callable<V> task) Submits the value to execute to return the task and returns the future that represents the result of the pending task. |
Future<V> |
submit(Runnable task, V result) Submits the Runnable task to be performed and returns a future that represents the completion of the task, which can be extracted or polled. |
Future<V> |
take() Gets and removes the future that represents the next completed task, and waits if no such task exists at this time. |
Examples of JDK's own:
Suppose you have a set of solvers for a problem, each solver can return some type of result value, and you want to run them at the same time, using the method use (Result R) to handle the return result of each solver that returns a non-null value. You can write programs like this
voidSolve (Executor E, collection<callable<result>>solvers)throwsinterruptedexception, executionexception {completionservice<Result> ECS =NewExecutorcompletionservice<result>(e); for(callable<result>s:solvers) Ecs.submit (s); intn =solvers.size (); for(inti = 0; I < n; ++i) {Result R=Ecs.take (). get (); if(r! =NULL) use (r); } }
Assume that you want to use the first non-null result in a task set, ignoring any task that encounters an exception, and cancel all other tasks when the first task is ready:
voidSolve (Executor E, collection<callable<result>>solvers)throwsinterruptedexception {completionservice<Result> ECS =NewExecutorcompletionservice<result>(e); intn =solvers.size (); List<Future<Result>> futures =NewArraylist<future<result>>(n); Result result=NULL; Try { for(callable<result>s:solvers) Futures.add (Ecs.submit (s)); for(inti = 0; I < n; ++i) {Try{Result R=Ecs.take (). get (); if(r! =NULL) {result=R; Break; } } Catch(Executionexception ignore) {}}} finally { for(future<result>f:futures) F.cancel (true); } if(Result! =NULL) use (result); }
Self-written example: (who gets the results first and I get the results first)
ImportJava.util.Random;Importjava.util.concurrent.Callable;ImportJava.util.concurrent.CompletionService;Importjava.util.concurrent.ExecutionException;ImportJava.util.concurrent.ExecutorCompletionService;ImportJava.util.concurrent.ExecutorService;Importjava.util.concurrent.Executors;Importjava.util.concurrent.Future; Public classThreadPool2 { Public Static voidMain (string[] args) {test2 (); } Private Static voidtest2 () {Executorservice es= Executors.newfixedthreadpool (5); Completionservice<Integer> cs =NewExecutorcompletionservice<integer>(es); for(intI=1; i<=5; i++){ Final intTask =i; Cs.submit (NewCallable<integer>() {@Override PublicInteger Call ()throwsException {Try{Thread.Sleep (NewRandom (). Nextint (5000)); } Catch(interruptedexception e) {e.printstacktrace (); } System.out.println ("Callable Task" "+ Task +" "Run Complete"); return NewRandom (). Nextint (100); } }); } System.out.println ("I'm the code before the results."); //asynchronously fetching results for(inti=0; i<5; i++){ Try{System.out.println (Cs.take (). get ()); } Catch(interruptedexception e) {e.printstacktrace (); } Catch(executionexception e) {e.printstacktrace (); }} System.out.println ("I'm the code after the results."); Es.shutdown (); }}
Results of the operation:
I am the code before the results callable task"3" run complete callable task"1" run complete callable task "4" Run completecallable task "5" Run completecallable task "2" Run complete 4 I was the code after the result
11, Java5 thread pool of asynchronous task Completionservice