This article is mainly concerned with the Executorservice in the Java.util.concurrent package. Executorservice is the implementation of the thread pool in Java.
I. Introduction of Executorservice
Executorservice is an interface defined in Java for the thread pool, which java.util.concurrent
defines the methods associated with background task execution in this interface:
There are two implementations of the Java API for the Executorservice interface, so these two are Java thread pool implementation classes:
1. Threadpoolexecutor2. Scheduledthreadpoolexecutor
In addition, Executorservice also inherited the Executor
interface (note the executor interface and executors factory Class), this interface has only one execute()
method, and finally we look at the entire inheritance tree:
second, the creation of Executorservice
Creating an instance of what Executorservice (that is, the thread pool) requires G to be based on a specific scenario, but Java provides us with one Executors工厂类
that can help us easily create various types of executorservice thread pools, Executors altogether can create the following four types of thread pools:
1. Newcachedthreadpool creates a cacheable thread pool that is flexible to reclaim idle threads if the thread pool length exceeds the processing needs, and creates a new thread if it is not recyclable. 2. Newfixedthreadpool creates a thread pool that controls the maximum number of concurrent threads, and the excess threads wait in the queue. 3. Newscheduledthreadpool creates a fixed-length pool that supports timed and recurring task execution. 4. Newsinglethreadexecutor creates a single threaded thread pool that performs tasks with only a single worker thread, ensuring that all tasks are executed in the specified order (FIFO, LIFO, priority).
Note: Executors is just a factory class, and all of its methods return ThreadPoolExecutor
instances of ScheduledThreadPoolExecutor
these two classes.
third, the use of Executorservice
Executorservice Executorservice = Executors.newfixedthreadpool (N); Executorservice.execute ( New Runnable () {publicvoid run () { System. out. println ("asynchronous task");}); Executorservice.shutdown ();
Iv. Implementation of the Executorservice
Executorservice has the following execution methods:
- Execute (Runnable)- Submit (Runnable)- Submit (callable)- invokeany (...) -InvokeAll (...)
4.1 Execute (Runnable)
This method takes a runnable instance and executes asynchronously, see the following example:
Executorservice Executorservice = executors.newsinglethreadexecutor (); Executorservice.execute (New Runnable () {publicvoid run () { System. out. println ("asynchronous task");}); Executorservice.shutdown ();
One problem with this approach is that there is no way to know the outcome of a task's execution. If we want to get the task execution result, we can pass in an instance of callable (described below).
4.2 Submit (Runnable)
submit(Runnable)
And the execute(Runnable)
difference is that the former can return a future object, through the return of the future object, we can check whether the submitted task is completed, see the following examples of execution:
Future future = Executorservice.submit (new Runnable () {publicvoid run () { System. out. println ("asynchronous task");}); Future. Get (); // returns NULL if the task has finished correctly.
If the task execution completes, the future.get()
method returns a null. Note that the Future.get () method can cause blocking.
4.3 submit (callable)
submit(Callable)
and submit(Runnable)
similar, will return a future object, but in addition, submit (callable) received is a callable implementation, callable interface call()
method has a return value, you can return the results of the task execution, The method in the Runnable interface run()
is void
, and there is no return value. Take a look at the following example:
Future future = Executorservice.submit (new Callable () { public Object call () throws Exception {System. out . println ( " asynchronous callable " return " Callable Result " ;}); System. out . println ( " future.get () = " + future. get ());
If the task execution completes, the Future.get () method returns the result of the execution of the callable task. Note that the Future.get () method can cause blocking.
4.4 invokeany (...)
invokeAny(...)
The method receives a collection of callable, which does not return to the future, but returns the result of the execution of one of the tasks in all callable tasks. This method also does not guarantee which task will return the result of the execution, anyway it is one of them. Take a look at the following example:
Executorservice Executorservice =Executors.newsinglethreadexecutor (); Set<Callable<String>> Callables =NewHashset<callable<string>>(); Callables.add (NewCallable<string>() { PublicString Call () throws Exception {return "Task 1";}}); Callables.add (NewCallable<string>() { PublicString Call () throws Exception {return "Task 2";}}); Callables.add (NewCallable<string>() { PublicString Call () throws Exception {return "Task 3";}}); String result=Executorservice.invokeany (callables); System. out. println ("result ="+result); Executorservice.shutdown ();
You can try to execute the above code, each execution will return a result, and the returned result is a change, may return "Task2" is also "Task1" or other.
4.5 invokeall (...)
invokeAll(...)
And invokeAny(...)
similar also receives a callable collection, but the former executes will return a future list, which corresponds to each callable task after the execution of the next object. Here's an example of this:
Executorservice Executorservice =Executors.newsinglethreadexecutor (); Set<Callable<String>> Callables =NewHashset<callable<string>>(); Callables.add (NewCallable<string>() { PublicString Call ()throwsException {return"Task 1";}}); Callables.add (NewCallable<string>() { PublicString Call ()throwsException {return"Task 2";}}); Callables.add (NewCallable<string>() { PublicString Call ()throwsException {return"Task 3";}}); List<Future<String>> futures =Executorservice.invokeall (callables); for(future<string>future:futures) {System.out.println ("Future.get =" +future.get ());} Executorservice.shutdown ();
v. Closure of the Executorservice
It should be closed after we have finished the Executorservice, otherwise the thread inside it will remain in the running state .
For example, if the application is started by the main () method, after this main () exit, if the Executorservice in the application is not closed, the application will run. This occurs because a thread running in Executorservice prevents the JVM from shutting down.
If you want to close the thread executing in Executorservice, we can call the ExecutorService.shutdown()
method. After calling the shutdown () method, Executorservice does not close immediately, but it no longer receives the new task until all the current threads have finished executing and all tasks committed before shutdown () are executed.
If we want to close executorservice immediately, we can call the ExecutorService.shutdownNow()
method. This action skips all the tasks that are being performed and the tasks that have not been committed yet. However, it does not guarantee any of the tasks that are being performed, it is possible that they will be stopped, or it may be done.
Original link: 49443835
Java Thread Pool Executorservice understand