工作中遇到一个需求,需要通过多线程调用其他接口,再将得到的结果进行处理后返回给上层。因此, 主线程需要等待所有子线程执行完毕在执行。
实现的方法比较多,比如主线程调用sleep()方法、Thread的join()方法、CountDownLatch、CyclicBarrier等。本文选用CountDownLatch工具类,并结合线程池进行实现实现该功能。
public Resp getDatasourceListByOu(String ouId) {
ExecutorService executorService = Executors.newFixedThreadPool(4);
String Path1 = "url1";
String Path2 = "url2";
String Path3 = "url3";
String Path4 = "url4";
List<String> urlList = new ArrayList<>();
if (!"".equals(Path1)) {
urlList.add(Path1);
}
if (!"".equals(Path2)) {
urlList.add(Path2);
}
if (!"".equals(Path3)) {
urlList.add(Path3);
}
if (!"".equals(Path4)) {
urlList.add(Path4);
}
List<FutureTask<String>> taskList = new ArrayList<>();
CountDownLatch latch = new CountDownLatch(urlList.size());
for (String uri : urlList) {
FutureTask<String> futureTask = new FutureTask<>(new GetDataSourceListTask(ouId, uri, latch));
taskList.add(futureTask);
executorService.submit(futureTask);
}
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
String typeResult = "";
List<String> resultList = new ArrayList<>();
Resp resp = new Resp();
for (FutureTask<String> task : taskList) {
try {
typeResult = task.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
resp = JSON.parseObject(typeResult, resp.class);
List<String> typeList = resp.getData();
for (String typeNum : typeList) {
resultList.add(typeNum);
}
}
if (resp.getCode() == 200) {
return Resp.success(resultList);
} else {
return Resp.error(queryDataSourceTypeResp.getCode());
}
}
GetDataSourceListTask代码如下:
public class GetDataSourceListTask implements Callable<String> {
private final String ouId;
private final String url;
private final CountDownLatch latch;
public GetDataSourceListTask(String ouId, String url, CountDownLatch latch) {
this.ouId = ouId;
this.url = url;
this.latch = latch;
}
@Override
public String call() throws Exception {
Map<String,String> map = new HashMap<>();
map.put("ouId",ouId);
String s = HttpClientUtil.doGet(url, map);
latch.countDown();
return s;
}
}
总结:需要在主线程中初始化一个CountDownLatch对象,设置好计数器的数值。这里的数值必须和创建的任务数相同,否则主线程将会一直等待。然后
向Task类(Callable接口的实现类)中传入定义好的CountDownLatch对象,CountDownLatch可定义为final。主线程中调用latch.await()方法,Task类中调用latch.countDown()进行计数。