一:前言

首先使用多线程来处理,比较慢的数据这个在平常的业务是非常见的,但是有些场景比较复杂,我们如果使用多线程去处理的话,是不知道,异步代码里面的逻辑什么时候走完的,这时候就需要用到线程的异步了

二:异步回调实现

	CallServiceImpl.log.info("开始进入异步代码----------------");
	//这里需要注意的是,如果你服务器核心数比较少的话,这里每次请求都会单独开一个线程,如果频繁调用的话容易导致CPU飙升,导致服务挂掉
		ExecutorService executorService = Executors.newSingleThreadExecutor();
		CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
		//这个一定要用try catch包裹住你的业务代码,不然如果线上报错的话是没办法捕获到异常的,方便生产环境排查问题
			CallServiceImpl.log.info("开启异步" + Thread.currentThread().getName());
			if (CollectionUtil.isNotEmpty(callTemporaryEntityList)) {
				//分片插入
				int count = (int) Math.ceil(callTemporaryEntityList.size() / 500.0);
				if (count == 1) {
					try {
						callTemporaryMapper.batchInsertCallTemp(database, callTemporaryEntityList);
					} catch (Exception e) {
						e.printStackTrace();
					}
				} else {
					List<List<CallTemporaryEntity>> listPartition = Lists.partition(callTemporaryEntityList, count);
					// 分片批量插入
					for (List<CallTemporaryEntity> item : listPartition) {
						try {
							callTemporaryMapper.batchInsertCallTemp(database, item);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}
			return "批量插入数据成功";
		}, executorService).thenApply((result) -> {
			CallServiceImpl.log.info("异步任务执行完成,获取到结果" + result);
			//异步回调的结果,可以是一个对象也个事一个字符串
			//修改状态为待解析
			try {
				customerFileMapper.updateFileStatusAndInvalidCount(database, id, 1, invalidPhoneCount);
			} catch (Exception e) {
				e.printStackTrace();
			}
			CallServiceImpl.log.info("异步任务执行完成,修改文件状态:{}", id);
			executorService.shutdown();
			return "修改文件状态成功";
		});

三:总结

我觉得多线程的异步对于一些特殊需要回调的场景是非常有用的,所以这里记录一下,另外有一句话就是不懂线程池回调,就不要说自己精通并发哈哈!

04-03 15:19