一、概述

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. Codeforces Round #826 (Div. 3) A-E

    比赛链接 A 题解 知识点:模拟. 时间复杂度 \(O(n)\) 空间复杂度 \(O(n)\) 代码 #include <bits/stdc++.h> #define ll long lo ...

  2. springboot整合mybatis步骤以及错误集合

    1.首先在springboot项目中的pomx文件引入官方的依赖 <groupId>org.mybatis.spring.boot</groupId> <artifact ...

  3. GNN 101

    GNN 101 姚伟峰 http://www.cnblogs.com/Matrix_Yao/ GNN 101 Why Graph无处不在 Graph Intelligence helps It's t ...

  4. yaml使用

    yml使用 安装yaml pip install PyYaml yaml基本规则 # 1.大小写敏感 # 2.使用缩进表示层级关系, # 2.1 不能使用tab进行缩进,只能使用空格 # 2.2 缩进 ...

  5. 「浙江理工大学ACM入队200题系列」问题 B: 零基础学C/C++12——求平均值

    本题是浙江理工大学ACM入队200题第二套中的B题 我们先来看一下这题的题面. 由于是比较靠前的题目,这里插一句.各位新ACMer朋友们,请一定要养成仔细耐心看题的习惯,尤其是要利用好输入和输出样例. ...

  6. zk系列三:zookeeper实战之分布式锁实现

    一.分布式锁的通用实现思路 分布式锁的概念以及常规解决方案可以参考之前的博客:聊聊分布式锁的解决方案:今天我们先分析下分布式锁的实现思路: 首先,需要保证唯一性,即某一时点只能有一个线程访问某一资源: ...

  7. C++初阶(运算符重载汇总+实例)

    运算重载符 概念: 运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似. 函数原型: 返回值 operator操作符(参数列表) 注意: ...

  8. mindxdl--common--web_cert_utils.go

    // Copyright (c) 2021. Huawei Technologies Co., Ltd. All rights reserved.// Package common this file ...

  9. Selenium4+Python3系列(九) - 上传文件及滚动条操作

    一.上传文件操作 上传文件是每个做自动化测试同学都会遇到,而且可以说是面试必考的问题,标准控件我们一般用send_keys()就能完成上传, 但是我们的测试网站的上传控件一般为自己封装的,用传统的上传 ...

  10. Springboot优雅进行字段检验

    Springboot优雅进行字段检验 1.Controller VS Service 推荐与业务无关的放在controller层中进行校验,而与业务相关的放在service层中校验. 2.常用校验工具 ...