Java中的异步多线程技术

在开发中有时经常用到异步多线程技术来快速高效完成某些任务,那常用的异步多线程技术参考如下:

1,建立一个用户自定义线程池

/**
* 自定义用户线程池,
* 注意:避免系统默认的线程池出现的性能问题
*/
@Bean("myExecutor")
public Executor myExecutor() {
	ThreadPoolTaskExector executor = new ThreadPoolTaskExector();
	
	//核心线程数
	executor.setCorePoolSize(10);	
	
	//最大线程数
	executor.setMaxPoolSize(20);	
	
	//队列中等待处理的最大的数目
	executor.setQueueCapacity(200);	
	
	//线程空闲后的最大存活时间单位秒
	executor.setKeepAliveSeconds(120);
	
	//对拒绝task的处理策略
	//rejection-policy:当pool已经达到max size的时候,如何处理新任务
	//CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
	executor.setRejectedExecutionHandler(new ThreadPoolExector.CallerRunsPolicy());
	
	//线程名称前缀
	executor.setThreadNamePrefix("myExecutor-thread-pool-");
	return executor;
}

2,各种场景的异步多线程参考如下注释和代码片段

/**
Java技术
1,异步多线程并行执行
注意:
myExecutor 为自定义的线程池;
runAsync 方法不支持返回值
supplyAsync 可以支持返回值
**/
String param01 = "...";
int param02 = "...";
CompletableFuture.supplyAsync((param01, param02) -> {
	try {
		String msg = xxService.fun01(param01, param02);
		return msg;
	} catch(Exception e){
		throw e;
	} finally{
		// 最后执行
		// todo...
	}
},myExecutor);
/**
2,异步多线程并行执行,某线程执行完,然后再执行后续如回调操作,
注意:
myExecutor 为自定义的线程池;
whenComplete 和 whenCompleteAsync 的区别:
whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。
exceptionally:异常处理方法
*/
String param01 = "...";
int param02 = "...";
CompletableFuture.supplyAsync((param01, param02) -> {
	try {
		String msg = xxService.fun01(param01, param02);
		return msg;
	} catch(Exception e){
		throw e;
	} finally{
		// todo...
	}
},myExecutor).whenComplete((result, error) -> {	
	// 单线程内执行完,然后再执行后续回调等操作
	// 此处参数 result 其实就是上面返回的msg对象
	String msg2 = xxService.fun02(result);
	return msg2;
	// todo...
}).exceptionally((throwable) -> {
	// 异常时执行
	// todo...
	result "发生异常";
});
/**
3,异步多线程并行执行,某单个线程内又有串行执行,单线程内执行完,然后再执行后续如回调操作,
注意:
myExecutor 为自定义的线程池;
handle 方法和 thenApply 方法处理方式基本一样;不同的是:
handle 是在任务完成后再执行,还可以处理异常的任务。
thenApply 只可以执行正常的任务,任务出现异常则不执行 thenApply 方法
*/
String param01 = "...";
int param02 = "...";
CompletableFuture.supplyAsync((param01, param02) -> {
	// 第一次处理
	try {
		String msg = xxService.fun01(param01, param02);
		return msg;
	} catch(Exception e){
		throw e;
	} finally{
		// todo...
	}
},myExecutor).thenApply((result) -> {
	// 第二次处理,依赖第一次执行结果
	// 此处参数 result 其实就是上面返回的msg对象
	String msg2 = xxService.fun02(result);
	return msg2;
	// todo...	
}).whenComplete((result, error) -> {	
	// 单线程内前面执行完,然后再执行后续回调等操作
	// 此处参数 result 其实就是上面返回的msg2对象
	String msg3 = xxService.fun03(result);
	return msg3;
	// todo...
}).exceptionally((throwable) -> {
	// 异常时执行
	// todo...
	result "发生异常";
});



// handle 函数例子
String param01 = "...";
int param02 = "...";
CompletableFuture.supplyAsync((param01, param02) -> {
	// 第一次处理
	try {
		String msg = xxService.fun01(param01, param02);
		return msg;
	} catch(Exception e){
		throw e;
	} finally{
		// todo...
	}
},myExecutor).handle((result, throwable) -> {
	// 第二次处理,依赖第一次执行结果
	// 此处参数 result 其实就是上面返回的msg对象
	String msg2 = xxService.fun02(result);
	return msg2;
	// todo...	
}).whenComplete((result, error) -> {	
	// 单线程内前面执行完,然后再执行后续回调等操作
	// 此处参数 result 其实就是上面返回的msg2对象
	String msg3 = xxService.fun03(result);
	return msg3;
	// todo...
}).exceptionally((throwable) -> {
	// 异常时执行
	// todo...
	result "发生异常";
});
/**
4,异步多线程并行执行,某单个线程内又有串行执行,单线程内执行完,然后再执行后续如回调操作,
(1)两个线程任务连接,只要其中一个执行完成,就执行最后代码;
(2)两个线程任务连接,只有两个都执行完成,才执行最后代码;
注意:
myExecutor 为自定义的线程池;
runAfterEither 方法两个CompletionStage,任何一个完成了都会执行下一步的操作
runAfterBoth 方法两个CompletionStage,都完成了计算才会执行下一步的操作
*/

// 定义第一个 CompletableFuture 对象
String param01 = "...";
int param02 = "...";
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync((param01, param02) -> {
	// 第一次处理
	try {
		String msg = xxService.fun01(param01, param02);
		return msg;
	} catch(Exception e){
		throw e;
	} finally{
		// todo...
	}
},myExecutor).thenApply((result) -> {
	// 第二次处理,依赖第一次执行结果
	// 此处参数 result 其实就是上面返回的msg对象
	String msg2 = xxService.fun02(result);
	return msg2;
	// todo...	
}).whenComplete((result, error) -> {	
	// 单线程内前面执行完,然后再执行后续回调等操作
	// 此处参数 result 其实就是上面返回的msg2对象
	String msg3 = xxService.fun03(result);
	return msg3;
	// todo...
});



// 定义第二个 CompletableFuture 对象
String param03 = "...";
int param04 = "...";
CompletableFuture<String> cf2 = CompletableFuture.supplyAsync((param03, param04) -> {
	// 第一次处理
	try {
		String msg = xxService.fun01(param03, param04);
		return msg;
	} catch(Exception e){
		throw e;
	} finally{
		// todo...
	}
},myExecutor).thenApply((result) -> {
	// 第二次处理,依赖第一次执行结果
	// 此处参数 result 其实就是上面返回的msg对象
	String msg2 = xxService.fun02(result);
	return msg2;
	// todo...	
}).whenComplete((result, error) -> {	
	// 单线程内前面执行完,然后再执行后续回调等操作
	// 此处参数 result 其实就是上面返回的msg2对象
	String msg3 = xxService.fun03(result);
	return msg3;
	// todo...
});

String param05 = "..."; // 可从cf1获取值
String param06 = "...";	// 可从cf2获取值

// runAfterEither 方法任务其中之一完成就执行
// 线程任务一和二连接比较,最后只要其中有一个处理完成就执行该方法
cf1.runAfterEither(cf2, (param05, param06) -> {
	System.out.println("上面其中有一个已经完成了");
	//todo...
}).get();

// 线程任务一和二连接比较,最后只要其中有一个处理完成就执行该方法,另一写法
cf1.runAfterEither(cf2, new Runnable() {
	@Override
	public void run() {
		System.out.println("上面其中有一个已经完成了");
	}
}).get();
		
		

// runAfterBoth 方法两任务都完成才执行
// 线程任务一和二连接判断,最后只有两任务都处理完成就执行该方法
cf1.runAfterBoth(cf2, (param05, param06) -> {
	System.out.println("上面两个任务都已经完成了");
	//todo...
}).get();

// 线程任务一和二连接判断,最后只有两任务都处理完成就执行该方法,另一写法
cf1.runAfterBoth(cf2, new Runnable() {
	@Override
	public void run() {
		System.out.println("上面两个任务都已经完成了");
	}
}).get();
/**
5,异步多线程并行执行,某单个线程内又有串行执行,单线程内执行完,然后再执行后续如回调操作,
在预期合理时间内未完成业务执行,当执行到complete则返回complete值
注意:
myExecutor 为自定义的线程池;
complete 线程任务执行完成则以该线程结果为准;如果在规定的时间内未执行完成时,
执行到complete,则返回complete的值
*/
String param01 = "...";
int param02 = "...";
public static void complete() throws Exception {
	CompletableFuture<String> cf1 = CompletableFuture.supplyAsync((param01, param02) -> {
		// 第一次处理
		try {
			String msg = xxService.fun01(param01, param02);
			return msg;
		} catch(Exception e){
			throw e;
		} finally{
			// todo...
		}
	},myExecutor).thenApply((result) -> {
		// 第二次处理,依赖第一次执行结果
		// 此处参数 result 其实就是上面返回的msg对象
		String msg2 = xxService.fun02(result);
		return msg2;
		// todo...	
	}).whenComplete((result, error) -> {	
		// 单线程内前面执行完,然后再执行后续回调等操作
		// 此处参数 result 其实就是上面返回的msg2对象
		String msg3 = xxService.fun03(result);
		return msg3;
		// todo...
	});

	// 主动休眠等待2秒
	TimeUnit.SECONDS.sleep(2);

	// cf1 执行完成则以该结果为准;
	// 如果在规定的时间内前面未执行完成时执行complete,则返回complete值
	cf1.complete("业务处理执行超时");
	System.out.println("result: " + cf1.get());
}
/**
6,异步多线程并行执行,某单个线程内又有串行执行,单线程内执行完,然后再执行后续如回调操作,
(1)多个线程任务连接,只要其中一个执行完成,就执行最后代码;
(2)多个线程任务连接,只有多个都执行完成,才执行最后代码;
注意:
myExecutor 为自定义的线程池;
allOf 在这里我们可以将对各future实例添加到allOf方法中,然后通过future的get()方法获取future的状态,
如果allOf里面的所有线程未执行完毕,主线程会阻塞,直到allOf里面的所有线程都执行完毕,主线程就会被唤醒;
anyOf 调用方法与allOf基本相同,区别在于anyOf是其中一个执行完成则往下执行,anyOf的get()方法返回最先执行完的Future;
*/

// 定义第一个 CompletableFuture 对象
String param01 = "...";
int param02 = "...";
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync((param01, param02) -> {
	// 第一次处理
	try {
		String msg = xxService.fun01(param01, param02);
		return msg;
	} catch(Exception e){
		throw e;
	} finally{
		// todo...
	}
},myExecutor).thenApply((result) -> {
	// 第二次处理,依赖第一次执行结果
	// 此处参数 result 其实就是上面返回的msg对象
	String msg2 = xxService.fun02(result);
	return msg2;
	// todo...	
}).whenComplete((result, error) -> {	
	// 单线程内前面执行完,然后再执行后续回调等操作
	// 此处参数 result 其实就是上面返回的msg2对象
	String msg3 = xxService.fun03(result);
	return msg3;
	// todo...
});


// 定义第二个 CompletableFuture 对象
String param03 = "...";
int param04 = "...";
CompletableFuture<String> cf2 = CompletableFuture.supplyAsync((param03, param04) -> {
	// 第一次处理
	try {
		String msg = xxService.fun01(param03, param04);
		return msg;
	} catch(Exception e){
		throw e;
	} finally{
		// todo...
	}
},myExecutor).thenApply((result) -> {
	// 第二次处理,依赖第一次执行结果
	// 此处参数 result 其实就是上面返回的msg对象
	String msg2 = xxService.fun02(result);
	return msg2;
	// todo...	
}).whenComplete((result, error) -> {	
	// 单线程内前面执行完,然后再执行后续回调等操作
	// 此处参数 result 其实就是上面返回的msg2对象
	String msg3 = xxService.fun03(result);
	return msg3;
	// todo...
});


// 定义第三个 CompletableFuture 对象
String param05 = "...";
int param06 = "...";
CompletableFuture<String> cf3 = CompletableFuture.supplyAsync((param05, param06) -> {
	// 第一次处理
	try {
		String msg = xxService.fun01(param05, param06);
		return msg;
	} catch(Exception e){
		throw e;
	} finally{
		// todo...
	}
},myExecutor).thenApply((result) -> {
	// 第二次处理,依赖第一次执行结果
	// 此处参数 result 其实就是上面返回的msg对象
	String msg2 = xxService.fun02(result);
	return msg2;
	// todo...	
}).whenComplete((result, error) -> {	
	// 单线程内前面执行完,然后再执行后续回调等操作
	// 此处参数 result 其实就是上面返回的msg2对象
	String msg3 = xxService.fun03(result);
	return msg3;
	// todo...
});


// 1,allOf 方法演示
System.out.println("三个线程任务执行完成状态:" 
	+ cf1.isDone()+" ," + cf2.isDone()+" ," + cf3.isDone());
	
// 通过主线程对其它三个线程任务进行连接
CompletableFuture<Void> allOfTask = CompletableFuture.allOf(cf1, cf2, cf3);
allOfTask.get();//这里会等待三个线程任务都执行完成,才执行后续代码
System.out.println("三个线程任务执行完成状态:" 
	+ cf1.isDone()+" ," + cf2.isDone()+" ," + cf3.isDone());


//2,anyOf 方法演示,此处与上面 allOf 方法不能同时使用
CompletableFuture<Object> anyOfTask = CompletableFuture.anyOf(cf1, cf2, cf3);
System.out.println("三个线程任务其中之一结果:" + anyOfTask.get());
System.out.println("三个线程任务执行完成状态:" 
	+ cf1.isDone()+" ," + cf2.isDone()+" ," + cf3.isDone());	



// 综合例子,从海量产品数据中,每次分页取有限大小记录数量,
// 分批次进行多线程异步处理,所有线程任务都执行完成后才返回最后结果
public <String, String> handleProductAsync(List<Long> prodctIds){
	if (null == prodctIds || prodctIds.size() < 1) {
		return null;
	}
	//每页100条记录, 计算总页数
	int pageSize = 100;
	int totalNum = prodctIds.size();
	int allPages = 0;
	int modNum = totalNum % pageSize;
	if (0 == modNum) {
		allPages = totalNum % pageSize;
	} else {
		allPages = (totalNum - modNum) / pageSize + 1;
	}
	
	// 存放结果的map
	private Map<String, String> retMap = new HashMap<String, String>();
	
	//所有页数分批次进行异步多线程并行处理,
	//建立的CompletableFuture对象放到一个数组中
	CompletableFuture[] cfs = allPages.stream().map(
		pageNum -> CompletableFuture.supplyAsync(() -> {
			// todo...第一次处理
			List<Long> tempIds = prodctIds.stream()
				.skip((long)(pageNum - 1)*pageSize)
				.limit(pageSize)
				.collect(Collectors.toList());
			
			 Map<String, String> tempMap1 = xxxProductService.fun01(tempIds);
			 return tempMap1;
		},myExecutor).thenApply((result01) -> {
			// todo...第二次处理,依赖第一次执行结果
			// 此处 result01 其实就是上面返回的tempMap1对象			
			Map<String, String> tempMap2 = xxxProductService.fun02(result01);
			return tempMap2;
		}).whenComplete((result02, error) -> {
			// todo...单线程内前面执行完,然后再执行后续回调等操作
			// 此处 result02 其实就是上面返回的tempMap2对象
			String tempKey = "xxx";
			String tempVal = xxxProductService.fun03(result02);
			retMap.put(tempKey, tempVal);
		})
	).toArray(CompletableFuture[]::new);
	
	//连接数组中所有线程任务,等待任务都执行完毕才返回结果
	CompletableFuture.allOf(cfs).join();
	return retMap;
}

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值