java线程池submit与execute的区别

ThreadPoolExecutor的中的submit和FutureTask || 通过Executors 创建线程池的一些实例(Callable和Runnable的在其中的体现) 线程的创建方式,Callable接口和Future接口的配合,Runnable任务、Callable任务提交到线程池,他们之间的区别 阅读详情

1、例子代码,可以先忽略ReadWriteLock相关代码,重点看ExecutorService 就行。

public class ReadWriteLockTest {
	//private static Lock lock = new ReentrantLock();
	private static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
	private static Lock readLock = readWriteLock.readLock();
	private static Lock writeLock = readWriteLock.writeLock();

	private static int number = 0;

	public void read(Lock lock) {
		lock.lock();
		try {
			Thread.sleep(1000L);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("读线程" + Thread.currentThread() + "--" + number);
		lock.unlock();
		throw new RuntimeException();
	}

	public void write(Lock lock, int value) {
		lock.lock();
		try {
			Thread.sleep(1000L);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		number = value;
		System.out.println("写线程" + Thread.currentThread() + "--" + number);
		lock.unlock();
	}

	public static void main(String[] args) {
		ExecutorService executor = Executors.newFixedThreadPool(50);
		// executor.execute(new Runnable() {
		//
		// public void run() {
		// new ReadWriteLockTest().read(readLock);
		// //new ReadWriteLockTest().read(lock);
		// }
		// });
		//

		// Future future = executor.submit(new Runnable() {
		//
		// public void run() {
		// new ReadWriteLockTest().read(readLock);
		// //new ReadWriteLockTest().read(lock);
		// }
		// });
		// try {
		// future.get();
		// } catch (InterruptedException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// } catch (ExecutionException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }


		for (int i = 0; i < 20; i++) {
			executor.submit(new Runnable() {

				public void run() {
					new ReadWriteLockTest().read(readLock);
					// new ReadWriteLockTest().read(lock);
				}
			});
			executor.submit(new Runnable() {

				public void run() {
					new ReadWriteLockTest().write(writeLock, new Random().nextInt());
					// new ReadWriteLockTest().write(lock, new Random().nextInt());
				}
			});
		}


		// for (int i = 0; i < 20; i++) {
		// new Thread(new Runnable() {
		//
		// public void run() {
		// new ReadWriteLockTest().write(writeLock, new Random().nextInt());
		// //new ReadWriteLockTest().write(lock, new Random().nextInt());
		// }
		// }).start();
		// }
		// for (int i = 0; i < 20; i++) {
		// new Thread(new Runnable() {
		//
		// public void run() {
		// new ReadWriteLockTest().read(readLock);
		// // new ReadWriteLockTest().read(lock);
		// }
		// }).start();
		// }
	}
}

ExecutorService.execute方法代码如下:

    public void execute(Runnable command) {
            if (command == null)
                throw new NullPointerException();
                
            int c = ctl.get();
            if (workerCountOf(c) < corePoolSize) {
                if (addWorker(command, true))
                    return;
                c = ctl.get();
            }
            if (isRunning(c) && workQueue.offer(command)) {
                int recheck = ctl.get();
                if (! isRunning(recheck) && remove(command))
                    reject(command);
                else if (workerCountOf(recheck) == 0)
                    addWorker(null, false);
            }
            else if (!addWorker(command, false))
                reject(command);
        }

如果提交的任务不需要一个结果的话直接用execute()会提升很多性能。

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
    return new FutureTask<T>(runnable, value);
}

protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    return new FutureTask<T>(callable);
}

包装成FutureTask,当执行到run方法时,我们为何没有看到有Exception抛出来?真相在此,一个try–catch吞噬了所有异常:

public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            runner = null;
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

最后只有在get方法中才可以抛出异常,所以,使用submit时的注意了,执行时并没有抛出异常中断父线程的执行,而你还需要get一下才行,否则这问题很难找。

public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

    public V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        if (unit == null)
            throw new NullPointerException();
        int s = state;
        if (s <= COMPLETING &&
            (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
            throw new TimeoutException();
        return report(s);
    }

结论请自己脑补,区别都列出来了。

Java线程池中submit() 和 execute()方法有什么区别 点个关注,必回关。 阅读详情

相关推荐

Java 线程池execute和submit的区别

execute和submit的区别 方法 使用场景 是否有返回值 异常处理 execute 适用于不需要返回值的场景 无 线程内部如果发生异常,主线程无感知。异常会通过stdout方式显示,如果需要在日志中打印,需要单独设置。方法见示例3 submit 适用于需要获取返回值的场景 有 调用future get方法时,异常会抛出。如果不调用get方法,则无法获取。 示例1:execute使用 private static void executeDemo() { Runna

WLFIGHTER的专栏 956

多线程(二) | 彻底搞懂线程池-Executors

[原文约7000字] 上篇文章,我们讲解了通过Thread和 Runnable 使用线程的方法,并且演示了如何创建一个线程并启动,今天我们来聊一聊多线程中的线程池。 一、为什么要使用线程池 我们使用多线程的一个一般步骤是: 先创建一个线程,然后线程执行线程任务,线程任务执行完毕后,线程会被销毁。 但是线程的创建和销毁是比较耗费资源的。在高并发场景之下,如果需要开启大量的线程,而每个线程它执行任务所需的时间很短的情况下,那么线程的频繁的创建和销毁就会成为性能的瓶颈。所以线程池应运而生。线程池的主要功能

lsqingfeng的博客 4168

libcrypto.so.10(OPENSSL_1.0.2)(64bit) is needed by erlang-22.0.7-1.el7.x86_64

今天安装Rabbitmq的 erlang-22.0.7-1.el7.x86_64.rpmrpm包时遇到了这个坑,害找到说是不容易;错误信息在下面; [root@iz2zef7u84js1qeeq00ewwz RabbitMQ]# rpm -ivh erlang-22.0.7-1.el7.x86_64.rpm warning: erlang-22.0.7-1.el7.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID 6026dfca: NOKEY error:

qq_45782349的博客 5783

JAVA线程池submit详解 ,execute和submit提交任务的区别

JAVA线程池submit详解 ,execute和submit提交任务的区别

胖虎儿的博客 1万+

岭回归的MATLAB步骤

MATLAB 实现框架,它涵盖了从数据导入到岭回归的步骤,包括计算共线性、使用 MAE、MSE、R²、MAPE 进行评价,以及绘制相应的可视化图表。

subject625Ruben的博客 1090

自动驾驶感知融合算法拆解:从华为MDC案例看前融合与大融合的工程实现

本文深度解析了华为MDC平台在自动驾驶感知融合算法中的前沿工程实践,重点探讨了Camera-Lidar前融合与多传感器大融合的架构设计。通过异构融合架构、数据流优化和场景化应用,华为MDC平台实现了高效、安全的感知能力,显著提升了自动驾驶系统的性能与可靠性。

weixin_29198045的博客 535

线程池ThreadPoolExecutor的submit方法

Future submit(Callable task);     Future submit(Runnable task, T result);     Future submit(Runnable task); 三个重载方法,第一个很好理解,传入callable,本身call函数就有一个返回值,可以正常取得。 第二个第三个就不清楚怎么可以取到返回值了,因为Runnabl

ccityzh的博客 1万+

105、LLC谐振变换器的LTspice仿真建模

文章摘要:本文分享了LLC谐振变换器在LTspice中的仿真建模经验。作者从实际调试中炸管的教训出发,指出数学计算无法捕捉瞬态问题,必须通过仿真验证。详细介绍了半桥LLC主电路搭建、理想元件选择、开环增益扫频、闭环控制实现等关键步骤,重点讲解了启动过程、ZVS验证和短路保护等高风险工况的仿真技巧。文章提供了实用参数设置建议和LTspice代码片段,强调先开环后闭环的调试顺序,并提醒仿真结果需保留20%设计裕量。最后总结了谐振电流波形观察、死区时间优化等经验性建议。

Jack010169的博客 229

executor.execute()与 executor.submit()区别

方法则适用于需要获取任务结果、进行精细的异常处理、监控任务状态或可能需要取消任务的情况。提供了诸如检查任务是否已完成、阻塞等待任务完成、获取任务结果或取消任务等操作。方法更适合用于提交不需要返回结果、异常处理相对简单且不需要取消功能的任务。接口的任务,这类任务没有返回值,通常用于执行纯粹的操作或计算。方法,允许尝试取消尚未开始或正在进行的任务。:当提交的任务在执行过程中抛出异常时,该异常将被传递给线程的。提交一个任务时,无法直接获取任务执行的结果或状态。,所以无法直接取消已提交的任务或查询其执行状态。

qq_31532979的贺公子之数据科学与艺术博客,致力于科技向善,拥抱开源,要用技术的影响力来领导团队,而不是威权和职位! 3484

MSVS C# Matlab的混合编程系列2 - 构建一个复杂(含多个M文件)的动态库:

本节我们尝试将一个有很多函数和文件的Matlab算法文件集成到C#的项目里面。

山云的专栏 2070

时间序列预测 | Python实现ARIMAX和VARMAX时间序列数据预测

时间序列预测 | Python实现ARIMAX和VARMAX时间序列数据预测 目录时间序列预测 | Python实现ARIMAX和VARMAX时间序列数据预测基本介绍ARIMAXVARVARMAVARMAXSESHWES参考资料 基本介绍 本文介绍ARIMAX、VAR、VARMA和VARMAX基本概念及其Python程序设计。 ARIMAX 具有外源回归量的自回归整合移动平均值(ARIMAX)是 ARIMA 模型的扩展,其还包括外生变量的建模。 外生变量也称为协变量,可以被认为是并行输入序列,其在与

前程算法屋的博客 6689

Java线程池系列之execute和submit区别

这是几年前的一道面试题了,网上的答案一般都是 1. execute只能提交Runnable类型的任务,没有返回值,而submit既能提交Runnable类型任务也能提交Callable类型任务,返回Future类型。 2. execute方法提交的任务异常是直接抛出的,而submit方法是是捕获了异常的,当调用FutureTask的get方法时,才会抛出异常。 我们可能看过n多次但又忘了n多加1次,那么我们到底应该如何才能彻底理解和记住这两者的区别呢,这就要从ThreadPoolExecutor的根

forever的专栏 1万+

015、架构_配置文件_管理节点(proxymanager.ini)

该配置文件中的参数在后台配置,两种生效方式:*所有参数重启生效。*部分参数可以使用工具dbtool动态生效。动态生效命令为:dbtool-pm-load-config。配置文件“proxymanager.ini”用于设置元数据管理模块的信息。文件路径为“~/etc”。配置文件“proxymanager.ini”是普通的文本文件。默认值proxymanager-alarmconfutf8.txt。配置错误或不配置,PM无法连接MDS,无法服务。获取元数据失败超时处理时间。异常时请求启动对等回滚。

Oracle/MySQL 到 国产信创数据库|迁移 · 调优 · 信创替换 330

Java线程池submit和execute有什么区别?

**:** 在线程池中,`submit` 和 `execute` 都用于提交任务,但有明显区别。`execute` 仅支持 Runnable 接口,不返回结果,适用于无需关注执行结果的任务;而 `submit` 支持 Callable 和 Runnable,返回 Future 对象,可跟踪任务状态和获取结果。因此,选择方法需根据具体需求来决定。

yanpeng2580的博客 903

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Java - 线程池中submit和execute的区别

大家在平时开发中,肯定会有用到线程池。线程池也就是利用一种池化技术。将线程创建好后,保存起来,减少因为重复的创建和销毁而带来的资源消耗。submitexecute那么这两种方式有什么区别呢?本文就会详细的来讲讲。我们再来看下线程池的一个类关系图:execute函数是接口Executor下的方法。submit是接口下的方法。而Executor}另一方面,则是继承了Executor接口的基础上,定义了submitFuture

Zong_0915的博客 1828

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

java 线程池中 execute 和 submit 方法的区别

java 线程池中 execute 和 submit 方法的区别

Jaemon 1771

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

java 线程池 execute_Java线程池的submit和execute方法区别

线程池中的execute方法大家都不陌生,即开启线程执行池中的任务。还有一个方法submit也可以做到,它的功能是提交指定的任务去执行并且返回Future对象,即执行的结果。下面简要介绍一下两者的三个区别:1、接收的参数不一样2、submit有返回值,而execute没有用到返回值的例子,比如说我有很多个做validation的task,我希望所有的task执行完,然后每个task告诉我它的执行结...

weixin_32537261的博客 836

Java线程池类型以及execute和submit方法的区别

为什么要使用线程池 如果有非常的多的任务需要多线程来完成,且每个线程执行时间不会太长,这样频繁的创建和销毁线程,让效率降低。 有了线程池就不用创建更多的线程来完成任务,因为线程可以重用。线程池维护一个队列,队列中保存着处于等待(空闲)状态的线程。不用每次都创建新的线程。 Java中有四种类型的线程 newFixedThreadPool: 创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。 newCached

一只程序猿的博客 1944

Java线程池execute和submit的区别

ThreadPoolExecutor提供了两种方法来执行异步任务,分别是execute和submit,也是日常开发中经常使用的方法,那么它俩有什么区别呢?execute和submit都可以执行异步任务,但是有三大区别,分别是:1.语义上的区别,是否关心任务的执行情况和返回结果;2.遇到遇到是直接抛出还是先记录下来;3.异常线程是销毁重建还是继续复用。

LiZhen314的博客 1481

【Java-多线程】线程池 submit 和 execute 有什么区别?

线程池的submit()和execute()方法主要区别在于:execute()没有返回值且直接抛出异常,仅支持Runnable任务;而submit()返回Future对象,异常封装在Future中,支持Runnable和Callable任务。submit()底层仍调用execute(),但提供了任务包装和结果获取功能。建议需要获取结果或异常处理时使用submit(),简单异步执行则用execute()。两种方法分别适用于不同场景,开发者应根据具体需求选择。

ZGW0513的博客 490

一心多用多线程-细谈java线程池submit与execute的区别

深夜学习,发现ThreadPoolExecutor里面一个小知识点,故开热点连wifi怒写submit与execute方法的区别。1.问题的来源在看书的时候,涉及到java线程池问题的时候常常面临这样一个问题。当定义了一个Runnable对象想提交到线程池里面总是会看到不同的提交方法,产生的尬题如下:public class ThreadPoolDemo { public static cl

读书就是赚钱 3万+

Java线程池中的submit与execute:区别、应用场景及面试必问知识点--JVM基础(25)

在Java中,当我们需要执行大量异步任务时,通常会利用线程池来管理线程资源,以避免频繁创建和销毁线程带来的开销。execute()和submit()。虽然它们都用于执行任务,但它们之间有一些关键的区别,这些区别在实际应用和面试中都是重点考察的内容。下面,让我们来一探究竟。

guangzhi0633的专栏 974

Java线程池的submit和execute方法区别

线程池中的execute方法大家都不陌生,即开启线程执行池中的任务。 还有一个方法submit也可以做到,它的功能是提交指定的任务去执行并且返回Future对象,即执行的结果。 下面简要介绍一下两者的三个区别: 1、接收的参数不一样 2、submit有返回值,而execu...

chikao1673的博客 876
上一篇: Dubbo架构设计详解
下一篇: 同步,异步,阻塞,非阻塞及并发编程概念
wingahi
博客等级 码龄15年 15粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值