图中 Futures 就好比居民楼一层的信箱(每个信箱有房间编号),左侧的 t0,t2,t4 就好比等待邮件的居民,右侧的 t1,t3,t5 就好比邮递员
    如果需要在多个类之间使用 GuardedObject 对象,作为参数传递不是很方便,因此设计一个用来解耦的中间类,这样不仅能够解耦【结果等待者】和【结果生产者】,还能够同时支持多个任务的管理

    image.png

    1. public class TestGuardedObjectV3 {
    2. public static void main(String[] args) {
    3. for (int i = 0; i < 3; i++) {
    4. GuardedObjectV3 v3 = Fetures.createFeture();
    5. new Thread(() -> {
    6. log.debug("waiting id({})...", v3.getId());
    7. log.debug("get response id({}): [{}] lines", v3.getId(), ((List<String>) v3.get()).size());
    8. }).start();
    9. new Thread(() -> {
    10. try {
    11. List<String> lines = download();
    12. log.debug("download complete id({})...", v3.getId());
    13. Fetures.complete(v3.getId(), lines);
    14. } catch (IOException e) {
    15. e.printStackTrace();
    16. }
    17. }).start();
    18. }
    19. }
    20. }
    21. class Fetures {
    22. private static final ConcurrentHashMap<Integer, GuardedObjectV3> FETURES = new ConcurrentHashMap<>();
    23. private static final AtomicInteger ID_GENERATOR = new AtomicInteger();
    24. public static GuardedObjectV3 createFeture() {
    25. // 为每个 GuardedObject 分配一个 id
    26. int id = ID_GENERATOR.incrementAndGet();
    27. GuardedObjectV3 v3 = new GuardedObjectV3(id);
    28. // 放入公共位置,将来异步响应返回时,根据编号获取
    29. FETURES.put(id, v3);
    30. return v3;
    31. }
    32. public static void complete(int id, Object response) {
    33. // 异步响应完成,根据编号获取并移除
    34. GuardedObjectV3 v3 = FETURES.remove(id);
    35. if (v3 != null) {
    36. v3.complete(response);
    37. }
    38. }
    39. }
    40. /**
    41. * 添加多任务处理
    42. */
    43. class GuardedObjectV3 {
    44. private int id;
    45. private Object response;
    46. private final Object lock = new Object();
    47. public GuardedObjectV3(int id) {
    48. this.id = id;
    49. }
    50. public int getId() {
    51. return id;
    52. }
    53. public Object get() {
    54. synchronized (lock) {
    55. while (response == null) {
    56. try {
    57. lock.wait();
    58. } catch (InterruptedException e) {
    59. e.printStackTrace();
    60. }
    61. }
    62. return response;
    63. }
    64. }
    65. public void complete(Object response) {
    66. synchronized (lock) {
    67. this.response = response;
    68. lock.notifyAll();
    69. }
    70. }
    71. }