线程池提交执行任务中execute()方法和submit()的区别

简介

在线程池的使用中,我们一般用ThreadPoolExecutor来创建线程池,创建好线程池后会将任务提交给线程池来执行。在提交任务的时候,JDK为我们提供了两种不同的提交方式,分别是submit()excute(),那么它们两者之间有什么不同呢?相互之间有什么关系呢?下面简单的介绍下

方法来源不同

execut()是在线程池的顶级接口Executor中定义的,而且只有这一个接口,可见这个方法的重要性。

public interface Executor {

    void execute(Runnable command);
    
}

ThreadPoolExecutor类中有它的具体实现。

submit()是在ExecutorService接口中定义的,并定义了三种重载方式,具体可以查看JDK文档


<T> Future<T> submit(Callable<T> task);

Future<?> submit(Runnable task);

<T> Future<T> submit(Runnable task, T result);

AbstractExecutorService类中有它们的具体实现,而ThreadPoolExecutor继承了AbstractExecutorService类,所以也有得到submit方法。

接收的参数不同

根据前面列出来的方法签名,可以知道:
execute()方法只能接收实现Runnable接口类型的任务
submit()方法则既可以接收Runnable类型的任务,也可以接收Callable类型的任务。
RunnableCallable的区别是 前者没有返回值,后者可以有返回值,于是这就又引出了下一个区别

返回值不同

execute()的返回值是void,线程提交后不能得到线程的返回值。
submit()的返回值是Future,通过Future的get()方法可以获取到线程执行的返回值,get()方法是同步的,执行get()方法时,如果线程还没执行完,会同步等待,直到线程执行完成。

虽然submit()方法可以提交Runnable类型的参数,但执行Future方法的get()时,线程执行完会返回null,不会有实际的返回值,这是因为Runable本来就没有返回值

下面是JDK中对submit(Runnable task)方法的描述:

 /**
  * Submits a Runnable task for execution and returns a Future
  * representing that task. The Future's {@code get} method will
  * return {@code null} upon <em>successful</em> completion.
  */

异常的处理

通过查看任务的方法签名,
submit()执行Runnable/Callable的任务时,run()/call()方法没显式抛出异常。
execute()执行Runnable的任务时,run()方法有显式的抛出异常。
通过实验发现,用submit()提交任务,任务内有异常也不会打印异常信息。
用execute()方法执行任务,默认情况下,提交到线程池的任务,如果run()方法中有异常,会打印异常信息。
当调用Futureget()方法时,也能打印出任务执行异常信息。
所以,当用submit()提交线程时,run()orcall()方法尽量显式的catch异常,这样才不至于任务提交线程池后丢失异常信息。
测试代码如下:
两个线程:

class TestCallable implements Runnable {
    @Override
    public void run()  { 
        
        //try {  // 为了防止异常丢失,我们应该显式处理异常
            int a = 10 / 0;
        //} catch (Exception e) {
            //e.printStackTrace();
        //}
        
    }
}

class TestCallable implements Callable<Integer> {
    @Override
    public Integer call()  {
    	// 为了防止异常丢失,我们应该显式处理异常
        int a = 10 / 0;
        return 1;
    }
}

测试主类:

public static void main(String[] args) {

        ExecutorService executorService = Executors.newFixedThreadPool(2);

        // 在线程的执行方法里如果没有异常处理,以下几个都不会有异常信息打印,只要不调用Future的get方法
//        executorService.submit(new TestRunnable());
//        executorService.submit(new TestCallable());
//        Future<?> future = executorService.submit(new TestRunnable());
//        Future<Integer> future1 = executorService.submit(new TestCallable());

        // 下面才会打印异常信息
        // executorService.execute(new TestRunnable());
        Future<Integer> future2 = executorService.submit(new TestCallable());
        try {
            future2.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }

以上就是关于线程池中execute()submit()的不同介绍,如有错误请大家多多指正。

  • 18
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值