java.util.concurrent学习之 Executor

本文介绍了Java中线程池的概念及其实现方式,包括ExecutorService、ScheduledExecutorService等接口的具体含义,并通过示例展示了如何使用Executors创建不同类型的线程池。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先我们先来看一下Executor的继承树关系:


然后了解下各个接口或类的意思

Executor :最上层接口,里面只有execute的方法
ExecutorService : 继承Executor,提供了更多丰富的方法(submit,invokeAny,invokeAll),对ExecutorService的接口实现有两个(ThreadPoolExecutor,ScheduledThreadPoolExecutor)
				  这两个即是java线程池具体实现类。
AbstractExecutorService:ExecutorService执行方法的默认实现
ScheduledExecutorService:对其中的任务进行调度,比如延迟执行、定时执行等等
ScheduledThreadPoolExecutor:ScheduledExecutorService的实现,一个可定时调度任务的线程池
ThreadPoolExecutor:线程池,可以通过调用Executors以下静态工厂方法来创建线程池并返回一个ExecutorService对象
Executors :工厂类,创建(newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor)四种类型ExecutorService线程池。
		   它的方法返回的都是ThreadPoolExecutor、ScheduledThreadPoolExecutor这两个类的实例。

应用场景,一般用来起线程异步操作一些事情,应用代码

public class Test {
	public static void main (String[] args) throws Exception {

		ExecutorService fixedThreadPool = Executors.newFixedThreadPool(20);
		fixedThreadPool.execute(new Runnable() {
			public void run() {
					System.out.println("hahaha ");
			}
		});
		
		ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
		//任务调度延迟执行,使用Callable可以返回数据
		ScheduledFuture<String> schedule = scheduledThreadPool.schedule(new Callable<String>() {
			public String call() throws Exception{
				System.out.println("hahahahah ");
				return "xixi";
			}
		}, 5, TimeUnit.SECONDS); 
		
		String str = schedule.get();
		System.out.println(str);
		 
	}
}




<think>好的,我现在要解决用户遇到的Guava Futures.addCallback方法类型不匹配的问题。用户提到Hadoop用的是guava-27,而Hive用的是guava-19,版本不一致导致的问题。首先,我需要回忆Guava中ListenableFuture和Futures.addCallback的使用方法。 首先,用户可能是在代码中调用了Futures.addCallback,但参数类型不匹配。这可能是因为不同版本的Guava中,addCallback方法的参数要求不同。比如,在较新的版本中,可能需要一个Executor参数,而旧版本可能不需要。或者,ListenableFuture和FutureCallback的包路径可能有变化,比如从com.google.common.util.concurrent到某个其他包,导致类加载器加载了错误版本的类。 接下来,我需要确认不同Guava版本中addCallback的方法签名。例如,在Guava 19中,Futures.addCallback的签名可能是: public static <V> void addCallback(ListenableFuture<V> future, FutureCallback<? super V> callback) 而在较新的版本,比如27中,可能变成了: public static <V> void addCallback(ListenableFuture<V> future, FutureCallback<? super V> callback, Executor executor) 这样,用户如果按照新版的方法调用,传入了三个参数,但Hive加载的是旧版Guava,缺少第三个Executor参数,就会导致编译错误或运行时NoSuchMethodError。 另外,还要考虑类加载冲突的问题。如果Hadoop和Hive分别依赖不同版本的Guava,而类加载器优先加载了旧版本的Guava,那么当代码试图调用新版本的方法时,就会找不到方法,出现错误。 解决方法可能包括: 1. 统一Guava版本:确保所有组件(Hadoop、Hive等)使用同一版本的Guava。但实际操作中可能困难,因为Hadoop和Hive可能有自己的依赖管理,强行替换版本可能导致其他兼容性问题。 2. 隔离类加载器:通过自定义类加载器,使得用户代码使用正确版本的Guava。比如在提交作业时,使用Hadoop的类加载隔离机制,确保用户代码的Guava版本优先被加载。 3. 适配代码:根据实际使用的Guava版本调整代码。例如,如果Hive环境中的Guava是19,则修改代码,去掉Executor参数,使用两参数的addCallback方法。但需要注意,这可能影响异步执行的行为,因为Executor参数控制回调的执行上下文。 用户需要检查他们的代码中调用addCallback的方式,以及运行时实际加载的Guava版本。如果代码是为Guava 27编写的,而运行时加载的是19,那么确实会出现方法签名不匹配的问题。这时候,可能需要调整代码,或者在构建时shade Guava库,重命名包路径以避免冲突。 另外,用户需要确认Hive和Hadoop的依赖路径,查看是否有办法排除旧版的Guava,或者升级Hive的Guava版本,但这可能会影响Hive的正常运行,需要谨慎处理。 总结下来,用户的问题核心在于依赖冲突,需要统一Guava版本或者调整代码以适应旧版本的方法签名。</think>要解决`Futures.addCallback`的类型不匹配问题,需关注**Guava版本兼容性**和**方法签名差异**。以下是具体分析和解决方案: --- ### 一、问题原因 1. **版本冲突** Hadoop依赖`guava-27`,而Hive加载了`guava-19`,导致调用`Futures.addCallback`时因方法签名不一致出现类型不匹配错误[^1]。 2. **方法签名差异** - **Guava 19及以下版本**:`addCallback`仅接受两个参数: ```java Futures.addCallback(ListenableFuture<V>, FutureCallback<V>) ``` - **Guava 20及以上版本**:新增了`Executor`参数: ```java Futures.addCallback(ListenableFuture<V>, FutureCallback<V>, Executor) ``` 若代码基于新版编写但运行环境加载了旧版Guava,会因缺少`Executor`参数报错。 --- ### 二、解决方案 #### 方法1:统一Guava版本(推荐) - **步骤**: 1. 检查Hive和Hadoop的依赖树,确认Guava版本冲突路径: ```bash mvn dependency:tree | grep guava ``` 2. 在项目中显式声明Guava版本(例如27.0-jre),并通过`<exclusion>`移除旧版本依赖: ```xml <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>27.0-jre</version> </dependency> ``` 3. 使用Shade插件重写Guava包路径,避免类加载冲突: ```xml <relocation> <pattern>com.google.common</pattern> <shadedPattern>my_shaded_package.com.google.common</shadedPattern> </relocation> ``` #### 方法2:适配旧版Guava - **代码调整**: 若无法升级Guava,需移除`Executor`参数并使用旧版方法: ```java // Guava 19兼容写法 Futures.addCallback(future, new FutureCallback<V>() { @Override public void onSuccess(V result) { /* ... */ } @Override public void onFailure(Throwable t) { /* ... */ } }); ``` **注意**:回调会在`ListenableFuture`的默认线程池执行,可能影响性能。 --- ### 三、验证步骤 1. **检查运行时Guava版本**: ```java System.out.println(com.google.common.base.Strings.class.getProtectionDomain().getCodeSource().getLocation()); ``` 2. **日志分析**: 捕获错误日志,确认是否因`NoSuchMethodError`导致类型不匹配。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值