一、概述

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. 死磕面试系列,Java到底是值传递还是引用传递?

    Java到底是值传递还是引用传递? 这虽然是一个老生常谈的问题,但是对于没有深入研究过这块,或者Java基础不牢的同学,还是很难回答得让人满意. 可能很多同学能够很轻松的背出JVM.分布式事务.高并发 ...

  2. Java安全之反序列化(1)

    序列化与反序列化 概述 Java序列化是指把Java对象转换为字节序列的过程:这串字符可能被储存/发送到任何需要的位置,在适当的时候,再将它转回原本的 Java 对象,而Java反序列化是指把字节序列 ...

  3. springcloud组件梳理之Feign

    最近刚好打算做一个springcloud系列的分享,趁此机会刚好梳理下springcloud常用组件的使用,今天先对feign做个简单介绍! feign是一个声明式的Web服务客户端,它使得发送web ...

  4. vue 过滤器时间格式化

    1.导入了一个moment.js插件,里面封装了格式化时间的方法 ①:插件的链接:https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/mom ...

  5. 第2-3-3章 文件处理策略-文件存储服务系统-nginx/fastDFS/minio/阿里云oss/七牛云oss

    目录 5.2 文件处理策略 5.2.1 FileStrategy 5.2.2 AbstractFileStrategy 5.2.3 LocalServiceImpl 5.2.4 FastDfsServ ...

  6. Vue+Go前端后端一体化 企业级微服务网关项目

    Vue+Go前端后端一体化 企业级微服务网关项目(~11) 课程目录: 第1章 拒绝培训机构烂大街项目,冲刺Offer首选[Vue+Go,稀缺组合,赶快上车!]1-1 摒弃千篇一律项目,选我:前后端一 ...

  7. IDEA项目下out与target目录的区别详解

    IDEA项目下out与target目录的区别详解 一.目录主要区别: out存放的是该项目下所有Module(模块)的编译结果. target存放的是单个Module的编译结果. 二.目录详解 out ...

  8. CmakeLists简单使用总结

    单文件工程和多级目录工程CmakeLists.txt编写分享 你若发现该帖中有待商榷的地方,还请指正赐教,先行拜谢了! 1 main.c单文件工程CmakeLists.txt 1.1 目录结构 1.2 ...

  9. SUPERVISOR监控tomcat配置文件

    Supervisor安装教程参考:https://www.cnblogs.com/brad93/p/16639953.html tomcat安装教程参考:https://www.cnblogs.com ...

  10. Java框架--SSM&Oracle&Maven高级

    〇.内容介绍 一.MyBatis01:框架概述.环境搭建及入门案例.自定义框架 1.介绍 框架:封装细节,是开发中的解决方案 三层架构与SSM的关系 表示层web:SpringMVC框架 业务层ser ...