• ExecutorService


    An Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks.

    An ExecutorService can be shut down, which will cause it to reject new tasks. Two different methods are provided for shutting down an ExecutorService. The shutdown() method will allow previously submitted tasks to execute before terminating, while the shutdownNow() method prevents waiting tasks from starting and attempts to stop currently executing tasks. Upon termination, an executor has no tasks actively executing, no tasks awaiting execution, and no new tasks can be submitted. An unused ExecutorService should be shut down to allow reclamation of its resources.

    Method submit extends base method execute(Runnable) by creating and returning a Future that can be used to cancel execution and/or wait for completion. Methods invokeAny and invokeAll perform the most commonly useful forms of bulk execution, executing a collection of tasks and then waiting for at least one, or all, to complete. (Class ExecutorCompletionService can be used to write customized variants of these methods.)

    The Executors class provides factory methods for the executor services provided in this package.

    Usage Examples

    Here is a sketch of a network service in which threads in a thread pool service incoming requests. It uses the preconfigured newFixedThreadPool(int) factory method:

     classNetworkServiceimplementsRunnable{
       
    privatefinalServerSocket serverSocket;
       
    privatefinalExecutorService pool;

       
    publicNetworkService(int port,int poolSize)
           
    throwsIOException{
         serverSocket
    =newServerSocket(port);
         pool
    =Executors.newFixedThreadPool(poolSize);
       


       
    publicvoid run(){// run the service
         
    try{
           
    for(;;){
             pool
    .execute(newHandler(serverSocket.accept()));
           
    }
         
    }catch(IOException ex){
           pool
    .shutdown();
         
    }
       
    }
     
    }

     
    classHandlerimplementsRunnable{
       
    privatefinalSocket socket;
       
    Handler(Socket socket){this.socket = socket;}
       
    publicvoid run(){
         
    // read and service request on socket
       
    }
     
    }}

    The following method shuts down an ExecutorService in two phases, first by calling shutdown to reject incoming tasks, and then calling shutdownNow, if necessary, to cancel any lingering tasks:

     void shutdownAndAwaitTermination(ExecutorService pool){
       pool
    .shutdown();// Disable new tasks from being submitted
       
    try{
         
    // Wait a while for existing tasks to terminate
         
    if(!pool.awaitTermination(60,TimeUnit.SECONDS)){
           pool
    .shutdownNow();// Cancel currently executing tasks
           
    // Wait a while for tasks to respond to being cancelled
           
    if(!pool.awaitTermination(60,TimeUnit.SECONDS))
               
    System.err.println("Pool did not terminate");
         

       
    }catch(InterruptedException ie){
         
    // (Re-)Cancel if current thread also interrupted
         pool
    .shutdownNow();
         
    // Preserve interrupt status
         
    Thread.currentThread().interrupt();
       
    }
     
    }}

    Memory consistency effects: Actions in a thread prior to the submission of a Runnable or Callable task to an ExecutorService happen-before any actions taken by that task, which in turn happen-before the result is retrieved via Future.get().

    An asynchronous process is a process which has the probability to not finishing its execution right away, but later. If the execution finishes right away, then those are known as synchronous process. Special care is needed when designing asynchronous process, because we are used to synchronous programming model.

    The java.util.concurrent.ExecutorService interface represents an asynchronous execution mechanism which is capable of executing tasks in the background. It extends Executor interface.

    Implementation of Executor service
    Here are the type of thread pools you can create with the Executors class, which are got from the factory class called Executors. Following are the implementation of ExecutorService :
    Single Thread Executor : A thread pool with only one thread. So all the submitted task will be executed sequentially.
    Method : Executors.newSingleThreadExecutor()
    Cached Thread Pool : A thread pool that create as many threads it needs to execute the task in parralel. The old available threads will be reused for the new tasks. If a thread is not used during 60 seconds, it will be terminated and removed from the pool.
    Method : Executors.newCachedThreadPool()
    Fixed Thread Pool : A thread pool with a fixed number of threads. If a thread is not available for the task, the task is put in queue waiting for an other task to ends.
    Method : Executors.newFixedThreadPool()
    Scheduled Thread Pool : A thread pool made to schedule future task.
    Method : Executors.newScheduledThreadPool()
    Single Thread Scheduled Pool : A thread pool with only one thread to schedule future task.
    Method : Executors.newSingleThreadScheduledExecutor()

    So we can create our ExecutorService like this:

    ExecutorService executorService1 = Executors.newSingleThreadExecutor();
    ExecutorService executorService2 = Executors.newFixedThreadPool(4);
    ExecutorService executorService3 = Executors.newScheduledThreadPool(4);
    


    Methods in Executor Service
    There are a few different ways to delegate tasks for execution to an ExecutorService:

    • execute(Runnable) - The execute(Runnable) method takes a java.lang.Runnable object, and executes it asynchronously.There is no way of obtaining the result of the executed Runnable.
    • submit(Runnable) - The submit(Runnable) method also takes a Runnable implementation, but returns a Future object. This Future object can be used to check if the Runnable as finished executing.
    • submit(Callable)-The submit(Callable) method is similar to the submit(Runnable) method except for the type of parameter it takes. The Callable instance is very similar to a Runnable except that its call() method can return a result. The Runnable.run() method cannot return a result.
    • invokeAny(...) - The invokeAny() method takes a collection of Callable objects, or subinterfaces of Callable. Invoking this method does not return a Future, but returns the result of one of the Callable objects. You have no guarantee about which of the Callable's results you get. Just one of the ones that finish.
    • invokeAll(...) - The invokeAny() method takes a collection of Callable objects, or subinterfaces of Callable. Invoking this method does not return a Future, but returns the result of one of the Callable objects. You have no guarantee about which of the Callable's results you get. Just one of the ones that finish.


    Lets look at them one by one. First get the instance of executor service:

    ExecutorService executorService = Executors.newSingleThreadExecutor();
    


    execute()
    Example to be added soon.
    submit()
    submit() takes callable and returns Future object.

    Callable c = new Callable() {
         public Object call() throws Exception {
             Thread.sleep(3000);
              ReturnObject rt =  new ReturnObject();
              rt.setReturnName(“serkan sunel”);
              return rt;
          }
      };
    
      Future future = executorService.submit(c);
    //Now get the result 
      try {
           Object returnObj = future.get();
           System.out.println(“returned :+ returnObj);
      } catch (Exception e) {
           e.printStackTrace(); 
      }
    


    So we can get result of the thread.

    Closing the ExecutorService
    You can close the executor service by calling shutdown() method. But this will not shut down immediately, but it will no longer accept new tasks, and once all threads have finished current tasks, the ExecutorService shuts down. All tasks submitted to the ExecutorService before shutdown() is called, are executed. You can use shutdownNow() to shutdown the service immediately.

    Example
    We are going to look into a program, which will initialize a fixed pool size ExecutorService and submit number of tasks (threads) to the executor service to execute them. To simulate asynchronous behavior each of those threads will work, and the sleep for a while, and then again work before returning result.

    public class ExecutorServiceWithCallable {
    
    public void executorServiceForCallable(int poolSize) throws 
                                       ExecutionException, InterruptedException {
    
            ExecutorService executorService = Executors.newFixedThreadPool(poolSize);
    
            List<Future> futures = new ArrayList<Future>();
            for (int index = 0; index < poolSize; index++) {
                Future future = executorService.submit(new RepeatingGreetings(index));
                futures.add(future);
            }
    
            for (Future future : futures) {
                System.out.println(future.get());
            }
    }
    class RepeatingGreetings implements Callable {
            private int index;
    
            RepeatingGreetings(int index) {
                this.index = index;
            }
    
            @Override
            public V call() throws Exception {
                System.out.println("Callable: " + index + " is working");
                int sleepValue = (int) (Math.random() * 1000);
                Thread.sleep(sleepValue);
                return (V) ("Callable: " + index + " sleept for: " + sleepValue);
            }
        }
    }
    


    First we are going to talk about the Callable we are creating, and then we will look into ExecutorService.

    Callable is same as java.lang.Runnable, both of them are designed to be executed by another thread. The only difference is, Callable is designed to return result, but Runnable are not. The call() method of Callable works same as run() method of Runnable.

    The use of Callable on our example is pretty straight forward. The RepeatingGreetings is Callable which will print a message, sleep for a random amount of time, and then return a string message as result of execution.

    The ExecutorServiceWithCallable is doing the main job here. We are creating a new executor service for supplied pool size. Then we are submitting our Callables to the ExecutorService to execute. As soon as we invoke the submit() method of ExecutorService the Callable are handed over to ExecutorService to execute. Here one thing we have to note, the submit() is not blocking. So, all of our Callables will be submitted right away to the ExecutorService, and ExecutorService will decide when to execute which callable. For each Callable we get a Future object to get the result later.

    Once the Callables are submitted for execution, we are iterating through all Futures to get the result of execution. We are invoking the get() method of Future to get the result. Here we have to remember that, the get() is a blocking method. So the first invocation of get() will wait until that Callable is finished. Once we receive the result of the execution of first Callable it will wait for next Callable to finish, and so on. Since the get() is blocking, we could put the iteration on a separate thread to continue the execution, and get the result later when all Futures are ready with their results.

    There is also, another useful method named isDone() on Future which let us check if the Callable for that Future is finished or not.

    Output
    The two random execution of our above example for five Callables produces output like

    Callable: 0 is working
    Callable: 1 is working
    Callable: 3 is working
    Callable: 2 is working
    Callable: 4 is working
    Callable: 4 sleept for: 18
    Callable: 0 sleept for: 70
    Callable: 1 sleept for: 449
    Callable: 3 sleept for: 744
    Callable: 2 sleept for: 844
    

    Another Random output -

    Callable: 0 is working
    Callable: 1 is working
    Callable: 3 is working
    Callable: 2 is working
    Callable: 4 is working
    Callable: 0 sleept for: 270
    Callable: 1 sleept for: 348
    Callable: 2 sleept for: 427
    Callable: 4 sleept for: 428
    Callable: 3 sleept for: 564
    
  • 相关阅读:
    【BZOJ5416】【NOI2018】冒泡排序(动态规划)
    【BZOJ4832】抵制克苏恩(矩阵快速幂,动态规划)
    【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)
    【BZOJ3142】[HNOI2013]数列(组合计数)
    【BZOJ3925】[ZJOI2015]地震后的幻想乡(动态规划)
    【Luogu4707】重返现世(min-max容斥)
    【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)
    【APIO2018】铁人两项(圆方树,动态规划)
    【BZOJ4005】[JLOI2015] 骗我呢(容斥,组合计数)
    【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)
  • 原文地址:https://www.cnblogs.com/qiengo/p/2976692.html
Copyright © 2020-2023  润新知