如果需要多个类之间使用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 {
@Override
public 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;
}
@Override
public 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<>();
// 产生唯一id
public 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();
}
}
}