如果需要多个类之间使用GuardedObject对象,作为参数传递不是很方便,因此设计一个解耦的中间类,这样不仅能够解耦结果的等待者和结果生产者,还能够支持多个任务的管理。
Futures就好比居民楼一层的信箱,每个信箱有房间的编号,左侧的t0,t2,t4就好比等待邮件的居民,右侧的t1,t3,t5就好比邮递员。
public class GuardedObjectMap {public static void main(String[] args) {//有三封信要送for (int i = 0; i < 3; i++) {new People().start();}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//邮递员送信Set<Integer> ids = EmailBox.getIds();for (int id: ids) {new Postman(id, "内容"+id).start();}}
}/*** 居民*/
class People extends Thread {@Overridepublic void run() {GuardedObjectObj guardedObjectObj = EmailBox.createGuardedObjectObj();System.out.println("开始收信index="+guardedObjectObj.getIndex());Object mail = guardedObjectObj.get(5000);System.out.println("收到信index="+guardedObjectObj.getIndex()+",内容="+mail);}
}/*** 邮递员*/
class Postman extends Thread {private int index;private String mail;public Postman(int index, String mail) {this.index = index;this.mail = mail;}@Overridepublic void run() {GuardedObjectObj guardedObjectObj = EmailBox.getGuardedObjectObj(index);System.out.println("开始送信index="+index+",内容="+mail);guardedObjectObj.complete(mail);}
}/*** 信箱*/
class EmailBox {//线程安全的集合private static Map<Integer, GuardedObjectObj> box = new ConcurrentHashMap<>();// 产生唯一idpublic static int id = 1;public static synchronized int generatedId() {// ++操作是线程不安全的要加锁return id++;}/*** 创建一个GuardedObjectObj对象并返回该对象,同时放入map中* @return*/public static GuardedObjectObj createGuardedObjectObj() {GuardedObjectObj guardedObjectObj = new GuardedObjectObj(generatedId());box.put(guardedObjectObj.getIndex(), guardedObjectObj);return guardedObjectObj;}/*** 根据index获取GuardedObjectObj* @param index* @return*/public static GuardedObjectObj getGuardedObjectObj(int index) {//因为box是静态的集合,使用完的对象一定要删除,防止堆内存溢出return box.remove(index);}/*** 获取所有GuardedObjectObj的keys* @return*/public static Set<Integer> getIds() {return box.keySet();}}class GuardedObjectObj {//标号(区分不同的GuardedObjectObj)private int index;public GuardedObjectObj(int index) {this.index = index;}public int getIndex() {return index;}private Object response;/*** 获取结果* @param timeout* @return*/public Object get(long timeout) {synchronized (this) {long start = System.currentTimeMillis();long usedTime = 0;while(response == null) {long waitTime = timeout - usedTime;if(waitTime <= 0) {break;}try {this.wait(waitTime);} catch (InterruptedException e) {e.printStackTrace();}usedTime = System.currentTimeMillis() - start;}return response;}}/*** 产生结果*/public void complete(Object response) {synchronized (this) {this.response = response;this.notifyAll();}}}