We now use multithreading in Java, usually not directly with the thread object, but will use the Executorservice class under the Java.util.concurrent package to initialize a thread pool for us to use.
I've been used to maintaining a list of the future objects returned by the callable task.
Traverse the list in the main thread and call the future's Get () method to fetch the return value of the task.
public class Completionservicetest {static class task implements Callable<string>{private int i;public task (int i) { THIS.I = i;} @Overridepublic String Call () throws Exception {Thread.Sleep (10000); return Thread.CurrentThread (). GetName () + "Perform task:" + i;}} public static void Main (string[] args) {testusefuture ();} private static void Testusefuture () {int numthread = 5; Executorservice executor = Executors.newfixedthreadpool (Numthread); list<future<string>> futurelist = new arraylist<future<string>> (); for (int i = 0;i< numthread;i++) {future<string> future = Executor.submit (new Completionservicetest.task (i)); FutureList.add ( Future);} while (Numthread > 0) {for (future<string> future:futurelist) {String result = null;try {result = Future.get (0, Tim Eunit.seconds);} catch (Interruptedexception e) {e.printstacktrace ();} catch (Executionexception e) {e.printstacktrace ();} catch ( TimeoutException e) {//timeout exception directly ignores}if (null! = result) {Futurelist.remove (future); numthread--; SYSTEM.OUT.PRINTLN (result);//must break here, otherwise a concurrency modification exception will be thrown. (can also be resolved by declaring futurelist as Copyonwritearraylist type);}}}}
However, in many places I see some code that wraps executorservice through Completionservice and then calls its take () method to fetch the future object.
public class Completionservicetest {static class task implements Callable<string>{private int i;public task (int i) { THIS.I = i;} @Overridepublic String Call () throws Exception {Thread.Sleep (10000); return Thread.CurrentThread (). GetName () + "Perform task:" + i;}} public static void Main (string[] args) throws Interruptedexception, Executionexception{testexecutorcompletionservice ( );} private static void Testexecutorcompletionservice () throws Interruptedexception, executionexception{int numthread = 5; Executorservice executor = Executors.newfixedthreadpool (Numthread); completionservice<string> completionservice = new executorcompletionservice<string> (executor); for (int i = 0;i<numthread;i++) {completionservice.submit (new Completionservicetest.task (i));}} for (int i = 0;i<numthread;i++) {System.out.println (Completionservice.take (). get ());}}
The difference between the two has not been studied before. After reading the source code today, I understand.
The main difference between the two is that the submit task does not necessarily follow the list order in which it is maintained.
Each future object that is traversed from the list is not necessarily in the completed state, and the call to get () method is blocked if the system is designed so that after each thread is finished it can continue to do what is behind it, This increases the additional wait time for threads that are behind the list but are completed first.
The implementation of Completionservice is to maintain a blockingqueue that holds the future object. Only when this future object state is finished will it be added to this queue, the take () method is actually the consumer in Producer-consumer. It will remove the future object from the queue, and if the queue is empty, it will block there until a completed future object is added to the queue.
Therefore, the first complete must be taken out first. This reduces unnecessary waiting times.
Executorservice and Completionservice differences in Java