CountDownLatch线程等待

异步请求

  创建一个使用okhttp发送get请求的方法,并将请求到的字符串结果return出来,由于使用的请求方式是异步请求,并不能马上得到响应值,所以最后return出去的还是null

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MyHttpRequest {
private String value;

public String myGet(String url){
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
value = "noValue";
}

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
value = response.body().string();\
}
});
return value;
}
}

  调用它,不出意外的话,一定是请求失败的

1
2
3
4
5
6
String value = myHttpRequest.myGet("https://www.baidu.com");
if (value == null || "noValue".equals(value)){
System.out.println("请求失败");
} else {
System.out.println("请求成功\n" + value);
}

等待请求结果

  如果要使其得请求结束后再return,让主线程等待子线程执行完毕
  使用countDownLatch类,使一个线程等待其他线程各自执行完毕后再执行。通过一个计数器来实现,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

  创建同步工具类,设置计数器初始值

1
CountDownLatch countDownLatch = new CountDownLatch(1);

  当请求失败或者请求成功时,计数器减一

1
countDownLatch.countDown();

  请求完毕后,执行await()阻塞线程,只有当计数器的值为0时,退出阻塞结束线程等待

1
2
3
4
5
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}

  看一下完整的myGet()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public String myGet(String url){
CountDownLatch countDownLatch = new CountDownLatch(1);//创建同步工具类,设置计数器初始值
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
value = "noValue";
countDownLatch.countDown();//计数器减一
}

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
value = response.body().string();
countDownLatch.countDown();//计数器减一
}
});
try {
countDownLatch.await();//阻塞当前线程,直到计数器为0退出
} catch (InterruptedException e) {
e.printStackTrace();
}
return value;
}

  再次从测试类中调用,一模一样的代码

1
2
3
4
5
6
7
String value = myHttpRequest.myGet("https://www.baidu.com");
if (value.equals("noValue")){
System.out.println("请求失败");
}
else {
System.out.println("请求成功\n" + value);
}

  可见请求成功,并输出了请求结果