一、概述

execute和submit都是线程池中执行任务的方法。

execute是Executor接口中的方法

public interface Executor {

    void execute(Runnable command);
}

submit是ExecuteService接口中的方法。

public interface ExecutorService extends Executor {

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

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

    Future<?> submit(Runnable task);
}

通过源码可以看出execute方法无返回值,参数为Runnable对象。

submit方法有三个重载方法,都有Future类型的返回值,参数可以是Runnable对象,Callable对象,Runnable对象和一个其他类型的对象。

那么在执行过程中有异常抛出会怎么样呢,先说答案,execute方法会直接抛出异常,submit方法不会抛出异常,只有在通过Future的get方法获取结果的时候才会抛出异常,下面进行测试:

public class ExecutorTest1 {

    public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
ExecutorTest1 test1 = new ExecutorTest1();
executorService.execute(() -> test1.say("execute方法"));
executorService.submit(() -> test1.say("submit方法"));
executorService.shutdown();
} private void say(String msg){
System.out.println(msg);
throw new RuntimeException("抛出了异常:"+ msg);
}
}

执行结果如下:



可见execute方法直接抛出了异常,submit方法只打印了参数没有抛出异常,下面测试使用Future的get方法获取结果:

public class ExecutorTest1 {

    public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
ExecutorTest1 test1 = new ExecutorTest1();
executorService.execute(() -> test1.say("execute方法"));
Future<?> submitFuture = executorService.submit(() -> test1.say("submit方法"));
try {
Object o = submitFuture.get();
System.out.println("这是submit的返回值:"+o);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executorService.shutdown();
} private void say(String msg){
System.out.println(msg);
throw new RuntimeException("抛出了异常:"+ msg);
}
}

结果如下:



可见使用submit方法时只有在使用Future的get方法时才会抛出异常,并且get方法也会抛出ExecutionException异常。

那么还有一个问题,如果线程中执行方法抛出的异常已经被捕获了,那么submit会怎么处理呢,其实在方法中如果异常已经被捕获了,那么就是方法的正常运行,有异常打印的话在执行的时候就会打印,不会等到调用Future的get方法时候才会打印。测试如下:

public class ExecutorTest1 {

    public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
ExecutorTest1 test1 = new ExecutorTest1();
executorService.execute(() -> test1.say("execute方法"));
Future<?> submitFuture = executorService.submit(() -> test1.say("submit方法"));
try {
Object o = submitFuture.get();
System.out.println("这是submit的返回值:"+o);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executorService.shutdown();
} private void say(String msg){
System.out.println(msg);
try{
throw new RuntimeException("抛出了异常:"+ msg);
}catch (Exception e){
e.printStackTrace();
}
}
}

结果如下:



可见execute和submit都正常执行了方法,Future的get方法也获取到了结果,因为say方法没有返回值,所以打印的结果是null。

二、结论

execute和submit的区别如下:

  1. execute是Executor接口的方法,submit是ExecuteService接口的方法。
  2. execute的入参是Runnable,submit的入参可以是Runnable、Callable、Runnable和一个返回值。
  3. execute没有返回值,submit有返回值。
  4. 方法中抛出异常,execute会直接抛出异常,submit会在获取结果的时候抛出异常,如果不获取结果,submit不抛出异常。

关于Future可以查看:

Java多线程:Future和FutureTask

之前文章:

HashMap源码解析(基于JDK1.8)

Java线程池详解

Java线程池中的execute和submit的更多相关文章

  1. Java 线程池中的线程复用是如何实现的?

    前几天,技术群里有个群友问了一个关于线程池的问题,内容如图所示: 关于线程池相关知识可以先看下这篇:为什么阿里巴巴Java开发手册中强制要求线程池不允许使用Executors创建? 那么就来和大家探讨 ...

  2. Java线程池中的核心线程是如何被重复利用的?

    真的!讲得太清楚了!https://blog.csdn.net/MingHuang2017/article/details/79571529 真的是解惑了 本文所说的"核心线程". ...

  3. Java线程池中线程的状态简介

    首先明确一下线程在JVM中的各个状态(JavaCore文件中) 1.死锁,Deadlock(重点关注) 2.执行中,Runnable(重点关注) 3.等待资源,Waiting on condition ...

  4. Java线程池中submit() 和 execute()方法的区别

    两个方法都可以向线程池提交任务, execute()方法的返回类型是void,它定义在Executor接口中, 而submit()方法可以返回持有计算结果的Future对象,它定义在ExecutorS ...

  5. Java线程池中submit()和execute()方法有什么区别

    两个方法都可以向线程池提交任务,execute()方法的返回类型是void,它定义在Executor接口中,而submit()方法返回有计算结构的Future对象,它定义在ExecutorServic ...

  6. Java 线程池中 submit() 和 execute()方法有什么区别?

    两个方法都可以向线程池提交任务,execute()方法的返回类型是 void,它定义在 Executor 接口中. 而 submit()方法可以返回持有计算结果的 Future 对象,它定义在 Exe ...

  7. JAVA线程池中的Callable和Future

    import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.Completio ...

  8. Java线程池ThreadPoolExecuter:execute()原理

    一.线程池执行任务的流程 如果线程池工作线程数<corePoolSize,创建新线程执行task,并不断轮训t等待队列处理task. 如果线程池工作线程数>=corePoolSize并且等 ...

  9. Java线程池中线程的生命周期

    设:我们有一个coreSize=10,maxSize=20,keepAliveTime=60s,queue=40 1.池初始化时里面没有任何线程. 2.当有一个任务提交到池就创建第一个线程. 3.若继 ...

  10. Java线程池中submit()和execute之间的区别?

    一: submit()方法,可以提供Future < T > 类型的返回值. executor()方法,无返回值. execute无返回值 public void execute(Runn ...

随机推荐

  1. 【原创】在RT1050 LittleVgl GUI中嵌入中文输入法框架

    时隔一年多终于又冒泡了,哎,随着工作越来越忙,自己踏实坐下来写点东西真是越来越费劲,这篇文章也是准备了好久好久才打算发表出来(不瞒大家,东西做完好久了,文章憋了一年了,当真"高产" ...

  2. js函数组合

    纯函数和柯里化容易引起洋葱代码 函数组合可以让我们把细粒度的函数重新组合生成一个新的函数 函数组合并没有减少洋葱代码,只是封装了洋葱代码 函数组合执行顺序从右到左 满足结合律既可以把g和h组合 还可以 ...

  3. C# 语法分析器(二)LR(0) 语法分析

    系列导航 (一)语法分析介绍 (二)LR(0) 语法分析 (三)LALR 语法分析 (四)二义性文法 (五)错误恢复 (六)构造语法分析器 首先,需要介绍下 LALR 语法分析的基础:LR(0) 语法 ...

  4. ES6 学习笔记(十二)代理器Proxy的简单使用

    1.前言 以前在学习react时做了个仿手机端的QQ音乐项目.当时的数据是通过proxy代理的QQ音乐数据接口,直接写在package.json里面.Proxy 对象(Proxy)是 ES6的特性,只 ...

  5. JVM堆内存转储

    在发生内存溢出错误 java.lang.OutOfMemoryError 时, JVM自动执行堆内存转储,以方便事后进行排查和分析. JVM提供了一个命令行启动参数 HeapDumpOnOutOfMe ...

  6. Java读取txt文件、excel文件的方法

    Java读取txt文件.excel文件的方法 1.读取txt文件 public static String getFileContent(String filePath,String charset) ...

  7. java学习之spirng的aop

    AOP技术 0x00前言 什么是AOP技术:在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的 ...

  8. 嵌入式-C语言基础:理解形参和实参的区别

    #include<stdio.h> //实参:函数原型中声明函数后面带的参数 int test(int x)//函数原型 { //函数体 printf("test里面的x地址=% ...

  9. 查看服务器出口ip

    [root@iZap201hv2fcgry1alvbznZ ~]# curl cip.cc IP : xxx.xxx.xx.xx 地址 : 中国 浙江 绍兴 运营商 : 移动 数据二 : 浙江省绍兴市 ...

  10. 深度探索Go语言:包装方法

    问题1:什么是包装方法? 下面咱们来验证下包装方法的存在: 首先,定义一个Point类型,表示一维坐标系内的一个点,并且按照Go语言的风格为其实现了一个Get方法和一个Set方法. package g ...