在使用多线程编程是,会用到三种
一、Thread
使用时重写run方法,void
二、Runnable
使用时重写run方法,void
三、Callable
使用时重写run方法,有返回值 <T>
返回值有两种,FutureTask<T> 和 Future<T>
Future是一个接口,代表可以取消的任务,并可以获得任务的执行结果
FutureTask 是基本的实现了Future和runnable接口 实现runnable接口,说明可以把FutureTask实例传入到Thread中,在一个新的线程中执行。具体学习请百度。
由于futureTask.get() 是阻塞式等待结果返回,在每一次提交到线程池执行后就调用get()方法阻塞获取结果,这样获取方式仍然不是异步获取。进一步对代码进行修改,把每一个线程对应futrueTask对象暂存到一个list或者map中,这样在所有任务均已提交执行后再去获取执行结果,如下代码所示:
//数据集合
Page<OmOracleInstance> page = (Page<OmOracleInstance>) instanceMapper.selectByExample(example);
// 创建一个大小为10的线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
//FutureTask 结果返回集合,用于存储异步返回结果
List<FutureTask<JSONObject>> futureTaskList = new ArrayList<>();
Stream<OmOracleInstance> stream = page.stream();
stream.forEach(tmp -> {
OmCntrOraInsDetail record = new OmCntrOraInsDetail();
record.setInstanceId(tmp.getId());
OmCntrOraInsDetail insDetail = insDetailMapper.selectOne(record);
//查询当前连接数,查询实例用户数,查看当前运行状态
JSONObject json = (JSONObject) JSONObject.toJSON(tmp);
JSONObject json1 = (JSONObject) JSONObject.toJSON(insDetail);
json1.putAll(json);
//多线程执行
SearchThread thread = new SearchThread(json1);
FutureTask<JSONObject> futureTask = new FutureTask<>(thread);
//提交线程
executorService.submit(futureTask);
futureTaskList.add(futureTask);
});
//关闭连接池
executorService.shutdown();
//异步获取执行结果
for(FutureTask<JSONObject> futureTask: futureTaskList ){
try{
array.add(futureTask.get());
}catch (Exception e){
log.error(e.getMessage(),e);
}
}
这样任务的执行是并行执行,获取结果是阻塞式获取,则服务运行的最长时间是最后执行完结果返回的时间,如果其中一个线程执行完成需要花费10s,但是其余99个线程在1s就已经执行完成,则获取主线程阻塞的时间是10s,如果更巧的是那个花费10s的线程刚好放在list的第一位,则其余99个线程的结果也需要在第10s之后才能够获取到,显然这存在一定的优化空间。
SearchThread 类 实现Callable<T>
@Slf4j
public class SearchThread implements Callable<JSONObject> {
private JSONObject json;
public SearchThread(JSONObject json){
this.json = json;
}
@Override
public JSONObject call() throws Exception {
//构造一个StringBuilder对象
StringBuilder sb = new StringBuilder(json.getString("name"));
//在指定的位置,插入指定的字符串
sb.insert(0, "[");
sb.insert(2,"]");
//远程连接
JSchSshUtils client = null;
try{
client = JSchSshUtilsFactory.createJschSession(json.getString("ip"), json.getString("username"),
json.getString("password"));//执行
//查询当前连接数
String linkers = client.execCommand(ShellEnum.INSTANCE_LINKERS.getCode());
json.put("linkers",Integer.parseInt(linkers.replace("\n",""))-1);
//查询当前运行状态
String runStatus = client.execCommand("ps -ef|grep "+sb.toString()+" |wc -l");
json.put("runStatus",runStatus.replace("\n",""));
//查询实例用户数
// String users = client.execCommand(ShellEnum.INSTANCE_USERS.getCode());
// json.put("users",users.replace("\n",""));
// json.put("result","success");
}catch (Exception e){
log.error(e.getMessage(),e);
json.put("result","fail");
json.put("msg",e.getMessage());
}finally {
JSchSshUtilsFactory.closeJschSession(client);
log.info("关闭SSH连接");
}
return json;
}
}

被折叠的 条评论
为什么被折叠?



