多线程之带返回值的异步线程启动方式-Callable
通常启动异步线程的时候 , 都是通过new Runnable或者new Thread的方式 . 在项目中实际使用的时候 , 很多都会配合线程池ThreadPoolExecutor来执行异步任务 .
最近在考虑的一个问题就是 , 假如在使用线程池的时候,需要针对某种业务场景获取异步线程的返回值,要怎么处理 . 这里某些程度上可以理解为是同步逻辑 .
例如 : 一个for循环中 , 通过线程池执行异步任务, 只有当参数 = a 的时候 , 才需要获取异步任务的返回值 , 这时候难不成还要把异步任务中的代码逻辑单独再单独拉出来一份么?
铺垫这么多 , 就是为了引入callable接口的使用 . 至于runnable接口的使用, 因为没写demo.就不说了 . 废话不多说,直接上代码 .
1. 构建,callable公共类 . 其中定义可重写的业务方法 .
package com.cloudtravel.common.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.Callable;
public class AbstractThreadCall implements Callable{
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractThreadCall.class);
/**
* 业务方法
* @return
*/
public Object execute(){
return "success";
};
public void logPrint(String logBase , Boolean error , Object ... args) {
if(error) {
LOGGER.error(logBase , args);
}else {
LOGGER.info(logBase , args);
}
}
@Override
public Object call() {
try {
return this.execute();
}catch (Throwable e) {
throw new RuntimeException("执行异常.......");
}
}
}
2.具体业务通过继承AbstractThreadCall类自定义参数并重写 execute()方法
public class ExcelCallUtil extends AbstractThreadCall{
private String param;
public ExcelCallUtil() {
super();
}
public ExcelCallUtil(String param) {
super();
this.param = param;
}
@Override
public String execute() {
try {
System.out.println(param + "开始");
System.out.println(param + "结束");
System.out.println();
}catch (Throwable e) {
this.logPrint("ExcelExecute Error , message = {}" , true , e.getMessage());
}
return "param = " + param;
}
}
3.线程池异步调用
@Test public void addRealNodes()throws Throwable { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10 , 100 , 0 , TimeUnit.MILLISECONDS , new LinkedBlockingQueue<>(100)); for (int i = 0 ; i < 10 ; i ++) { ExcelCallUtil excelCallUtil = new ExcelCallUtil("testParam"+i); Future<String> future = threadPoolExecutor.submit(excelCallUtil); System.out.println(); if(i % 10 == 0){ System.out.println(future.get()); } } System.out.println("Main end"); }