:::tips 用在一个线程等待另一个线程的执行结果 ::: image.png

要点

  • 有一个结果需要从一个线程传递到另一个线程,让他们关联同一个 GuardedObject
  • 如果有结果不断从一个线程到另一个线程那么可以使用消息队列(见生产者/消费者)
  • JDK 中,join 的实现、Future 的实现,采用的就是此模式
  • 因为要等待另一方的结果,因此归类到同步模式
  1. public class TestGuardedObject {
  2. public static void main(String[] args) {
  3. GuardedObject guardedObject = new GuardedObject();
  4. new Thread(() -> {
  5. try {
  6. List<String> response = download();
  7. log.debug("download complete...");
  8. guardedObject.complete(response);
  9. } catch (IOException e) {
  10. e.printStackTrace();
  11. }
  12. }).start();
  13. log.debug("waiting...");
  14. Object response = guardedObject.get();
  15. log.debug("get response: [{}] lines", ((List<String>) response).size());
  16. }
  17. }
  18. class GuardedObject {
  19. private Object response;
  20. private final Object lock = new Object();
  21. public Object get() {
  22. synchronized (lock) {
  23. // 条件不满足则等待
  24. while (response == null) {
  25. try {
  26. lock.wait();
  27. } catch (InterruptedException e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. return response;
  32. }
  33. }
  34. public void complete(Object response) {
  35. synchronized (lock) {
  36. // 条件满足,通知等待线程
  37. this.response = response;
  38. lock.notifyAll();
  39. }
  40. }
  41. }
  42. public class Downloader {
  43. public static List<String> download() throws IOException {
  44. HttpURLConnection conn = (HttpURLConnection) new URL("https://www.baidu.com/").openConnection();
  45. List<String> lines = new ArrayList<>();
  46. try (BufferedReader reader =
  47. new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
  48. String line;
  49. while ((line = reader.readLine()) != null) {
  50. lines.add(line);
  51. }
  52. }
  53. return lines;
  54. }
  55. }