java多线程异步

背景

最近遇到多数据库执行sql处理后生成报表,项目原有逻辑是单线程同步执行的,随着数据量的增大时间越来越长,我忍不住要优化。考虑一定得用多线程处理,那就首先需要线程池了,毕竟没有线程池的情况下很容易出现无休止创建线程是非常危险的。

实现

代码

伪代码

//创建线程池
ExecutorService executor = Executors.newFixedThreadPool(4);
CompletionService completionSevice = new ExecutorCompletionService(executor);

for (DatabaseNode databaseNode: databaseNodeList) {
    //提交请求到具体的库
     completionSevice.submit(new SqlHandler(properties, databaseNode, sql,         
     ModuleConstant.NODE_PASSWORD_KEY, encode, userType));

}


//获取执行结果
//databaseNodeList.size()只为获取节点个数,获取到的每个节点是没有顺序
 for (int i = 0; i < databaseNodeList.size(); i++) {
    Object result = null;
    DrdsNodes nodeSchema = null;
    //获取到每个库节点执行的结果,结果是从最先执行完的开始拿的,每次拿一个
    Map resultMap = (Map) 
          completionSevice.take().get();
  //后续根据具体业务操作
   。。。。

 }


/**
  *具体执行sql的类  (伪代码)
  *
 */
public class SqlHandler  implements Callable {
	
	private final String ddl;
	private JdbcTemplate jdbcTemplate;
    private DrdsNodes databaseNode;
	
	public SqlRowNumHandler(RdsProperties properties, DatabaseNode databaseNode, String ddl, String nodePwdKey,String encode, Integer userType) {
		
       //sql的构建封装代码

	}
	
   //类实现Callable,初始化时自动调用此方法
	@Override
    public Object call() throws Exception {
       //key 是数据库的实例,用以获取时区分是哪个库执行的结果
        Map resultMap = Maps.newHashMap();
        try {
            Object value = jdbcTemplate.update(ddl);
            resultMap.put(drdsNode, value);
            return resultMap;
        } catch (Exception e) {
            resultMap.put(drdsNode, e.getMessage());
            return resultMap;
        }
    }
 
  

注:completionSevice.take().get();是类似于指针一样获取结果(先执行完返回的先获取到)

CompletionService实现原理

CompletionService实际上可以看做是Executor和BlockingQueue的结合体。CompletionService在接收到要执行的任务时,通过类似BlockingQueue的put和take获得任务执行的结果。CompletionService的一个实现是ExecutorCompletionService,ExecutorCompletionService把具体的计算任务交给Executor完成。

测试后发现效率提高了5倍左右。

 

你可能感兴趣的:(多线程,异步,线程池)