• 技术文章 >Java >java教程

    JAVA中ThreadPoolExecutor线程池的submit方法详解

    怪我咯怪我咯2017-06-30 10:43:16原创3498
    下面小编就为大家带来一篇简单谈谈ThreadPoolExecutor线程池之submit方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    jdk1.7.0_79

    在上一篇《ThreadPoolExecutor线程池原理及其execute方法》中提到了线程池ThreadPoolExecutor的原理以及它的execute方法。本文解析ThreadPoolExecutor#submit。

    对于一个任务的执行有时我们不需要它返回结果,但是有我们需要它的返回执行结果。对于线程来讲,如果不需要它返回结果则实现Runnable,而如果需要执行结果的话则可以实现Callable。在线程池同样execute提供一个不需要返回结果的任务执行,而对于需要结果返回的则可调用其submit方法。

    回顾ThreadPoolExecutor的继承关系。

    在Executor接口中只定义了execute方法,而submit方法则是在ExecutorService接口中定义的。

    //ExecutorService
    public interface ExecutorService extends Executor {
      ...
      <T> Future<T> submit(Callable<T> task);
      <T> Future<T> submit(Runnable task, T result);
      <T> Future<T> submit(Runnable task);
      ...
    }

    而在其子类AbstractExecutorService实现了submit方法。

    //AbstractExecutorService
    public abstract class AbstractExecutorService implements ExecutorService {
      ...
      public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
      }
      public <T> Future<T> submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
      }
      public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerExeption();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask; 
      }
      ...
    }

    在AbstractExecutorService实现的submit方法实际上是一个模板方法,定义了submit方法的算法骨架,其execute交给了子类。(可以看到在很多源码中,模板方法模式被大量运用,有关模板方法模式可参考《模板方法模式》)

    尽管submit方法能提供线程执行的返回值,但只有实现了Callable才会有返回值,而实现Runnable的线程则是没有返回值的,也就是说在上面的3个方法中,submit(Callable<T> task)能获取到它的返回值,submit(Runnable task, T result)能通过传入的载体result间接获得线程的返回值或者准确来说交给线程处理一下,而最后一个方法submit(Runnable task)则是没有返回值的,就算获取它的返回值也是null。

    下面给出3个例子,来感受下submit方法。

    submit(Callable<T> task)

    package com.threadpoolexecutor;
    
    import java.util.concurrent.*;
    
    /**
     * ThreadPoolExecutor#sumit(Callable<T> task)
     * Created by yulinfeng on 6/17/17.
     */
    public class Sumit1 {
    
     public static void main(String[] args) throws ExecutionException, InterruptedException {
     Callable<String> callable = new Callable<String>() {
     public String call() throws Exception {
     System.out.println("This is ThreadPoolExetor#submit(Callable<T> task) method.");
     return "result";
     }
     };
    
     ExecutorService executor = Executors.newSingleThreadExecutor();
     Future<String> future = executor.submit(callable);
     System.out.println(future.get());
     }
    }

    submit(Runnable task, T result)

    package com.threadpoolexecutor;
    
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * ThreadPoolExecutor#submit(Runnable task, T result)
     * Created by yulinfeng on 6/17/17.
     */
    public class Submit2 {
    
     public static void main(String[] args) throws ExecutionException, InterruptedException {
    
     ExecutorService executor = Executors.newSingleThreadExecutor();
     Data data = new Data();
     Future<Data> future = executor.submit(new Task(data), data);
     System.out.println(future.get().getName());
     }
    }
    
    class Data {
     String name;
    
     public String getName() {
     return name;
     }
    
     public void setName(String name) {
     this.name = name;
     }
    }
    
    class Task implements Runnable {
     Data data;
    
     public Task(Data data) {
     this.data = data;
     }
     public void run() {
     System.out.println("This is ThreadPoolExetor#submit(Runnable task, T result) method.");
     data.setName("kevin");
     }
    }

    submit(Runnable task)

    package com.threadpoolexecutor;
    
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * ThreadPoolExecutor#sumit(Runnable runnables)
     * Created by yulinfeng on 6/17/17.
     */
    public class Submit {
    
     public static void main(String[] args) throws ExecutionException, InterruptedException {
     Runnable runnable = new Runnable() {
     public void run() {
     System.out.println("This is ThreadPoolExetor#submit(Runnable runnable) method.");
     }
     };
    
     ExecutorService executor = Executors.newSingleThreadExecutor();
     Future future = executor.submit(runnable);
     System.out.println(future.get());
     }
    }

    通过上面的实例可以看到在调用submit(Runnable runnable)的时候是不需要其定义类型的,也就是说虽然在ExecutorService中对其定义的是泛型方法,而在AbstractExecutorService中则不是泛型方法,因为它没有返回值。(有关Object、T、?这三者的区别,可参考《Java中的Object、T(泛型)、?区别》)。

    从上面的源码可以看到,这三者方法几乎是一样的,关键就在于:

    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);

    它是如何将一个任务作为参数传递给了newTaskFor,然后调用execute方法,最后进而返回ftask的呢?

    //AbstractExecutorService#newTaskFor
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
      return new FutureTask<T>(callable);
    }
      protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
      return new FutureTask<T>(runnable, value);
    }

    看来是返回了一个FutureTask实例,FutureTask实现了Future和Runnable接口。Future接口是Java线程Future模式的实现,可用用来异步计算,实现Runnable接口表示可以作为一个线程执行。FutureTask实现了这两个接口意味着它代表异步计算的结果,同时可以作为一个线程交给Executor来执行。有关FutureTask放到下章来单独解析。所以本文对于线程池ThreadPoolExecutor线程池的submit方法解析并不完整,必须得了解Java线程的Future模式——《老生常谈Java中的Future模式》。

    以上就是JAVA中ThreadPoolExecutor线程池的submit方法详解的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:java中的Future模式详解 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • 一起来分析java设计模式之单例• Java数据结构之单链表与OJ题• 一文搞懂Java线程池实现原理• 详细介绍Java正则表达式之单字符匹配和预定义字符• Java总结分享之反射、枚举、Lambda表达式
    1/1

    PHP中文网