美文网首页
ExecutorService的理解和使用

ExecutorService的理解和使用

作者: 极客匠 | 来源:发表于2019-12-30 23:21 被阅读0次

    ExecutorService表述了异步执行的机制,并且可以让任务在后台执行。一个ExecutorService实例就是一个线程池。

    ExecutorService实例

    ExecutorService executorService = Executors.newFixedThreadPool(10);
    executorService.execute(new Runable(){
     @Override
     public void run(){
     System.out.println("Asynchronus task");
     }
    });
    executorService.shutdown();
    

    Note: 首先通过newFixedThreadPool()工厂方法创建一个ExecutorService实例。上述代码创建了一个可以容纳10个线程任务的线程池。

    其次,向execute()方法中传递一个异步的runnable接口实现,这样做会让ExecutorService中的某一个线程执行这个Runnable线程。

    ExecutorService的实现

    创建ExecutorService是采用Executors工厂方法来创建的。以下有几个例子,代表创建不同的线程池

    创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
    ExecutorService executorService1 = Executors.newSingleThreadExecutor();
    //创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
    ExecutorService executorService2 = Executors.newFixedThreadPool(10);  
    
    //创建一个定长线程池,支持定时及周期性任务执行
    ExecutorService executorService3 = Executors.newScheduledThreadPool(10);  
    
    //创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
    ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    

    任务委托

    我们来展示一个线程的任务委托异步执行的ExecutorService的示意图。

    [图片上传失败...(image-7aedc5-1577719003067)]

    一旦线程把任务委托给ExecutorService,那么该线程就会继续执行与运行任务无关的其他任务

    ExecutorService使用方法

    1. execute(Runnable)

      接收一个runable对象作为参数,并且以异步的方式执行它。请看上面实例

    2. submit(Runnable)

      接收一个sunable对象作为参数,但是会返回一个Future对象。这个Future对象可以用于判断Runable是否结束执行。如下举例:

      Future future = executorService.submit(new Runnable() {  
         public void run() {
         System.out.println("Asynchronous task");
         }
        });  
        //如果任务结束执行则返回 null  
        System.out.println("future.get()=" + future.get());  </pre>
    
    3.  submit(Callable)
    
        和方法submit(Runable)类似。区别在于他们接收的参数类型不同。Callable的call方法可以返回一个结果,Runable.run()则不能返回结果。举例说明:
     ```java
      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());
    
    1. invokeAny(...)

      接收一个包含Callbable对象的集合作为参数。调用该方法会返回集合中的某一个Callable对象的结果,但无法保证调用之后返回的结果是哪一个Callable对象。如果一个任务执行完毕,或者抛出异常,方法会取消其他的Callable执行。举例说明:

    ExecutorService executorService = Executors.newSingleThreadExecutor();  
    Set<Callable<String>> callables = new HashSet<Callable<String>>();  
    
    callables.add(new Callable<String>() {  
     public String call() throws Exception {
     return "Task 1";
     }
    });  
    callables.add(new Callable<String>() {  
     public String call() throws Exception {
     return "Task 2";
     }
    });  
    callables.add(new Callable<String>() {  
     public String call() throws Exception {
     return "Task 3";
     }
    });  
    
    String result = executorService.invokeAny(callables);  
    
    System.out.println("result = " + result);  
    
    executorService.shutdown(); 
    
    1. invokeAll(...)

      调用存在于参数集合中的所有 Callable 对象,并且返回壹個包含 Future 对象的集合,你可以通过这個返回的集合来管理每個 Callable 的执行结果。需要注意的是,任务有可能因为异常而导致运行结束,所以它可能并不是真的成功运行了。举例说明:

      ExecutorService executorService = Executors.newSingleThreadExecutor();  
      Set<Callable<String>> callables = new HashSet<Callable<String>>();  
    
        callables.add(new Callable<String>() {  
         public String call() throws Exception {
         return "Task 1";
         }
        });  
        callables.add(new Callable<String>() {  
         public String call() throws Exception {
         return "Task 2";
         }
        });  
        callables.add(new Callable<String>() {  
         public String call() throws Exception {
         return "Task 3";
         }
        });  
    
        String result = executorService.invokeAll(callables);  
    
        System.out.println("result = " + result);  
    
        executorService.shutdown(); </pre>
    

    ExecutorService 关闭

    当使用完ExecutorService服务后,我们要关闭它。这样才能保证线程不会继续运行。如果没有关闭掉ExecutorService会导致程序继续保持运行状态,也会导致该进程无法被Java虚拟机关闭,出现可能的内存泄露情况。所以为了关闭ExecutorService中的线程,可以调用shutdown方法。这个方法不会马上关闭线程,而是不再接收新的任务。等到所有的线程都结束执行当前的任务,ExecutorService才会真的关闭。如果希望马上关闭Executorservice,可以调用shutdownNow()。

    相关文章

      网友评论

          本文标题:ExecutorService的理解和使用

          本文链接:https://www.haomeiwen.com/subject/eejvoctx.html