并发编程-同步模式之保护性暂停

同步模式之保护性暂停即 Guarded Suspension,用在一个线程等待另一个线程的执行结果
要点
有一个结果需要从一个线程传递到另一个线程,让他们关联同一个 GuardedObject
如果有结果不断从一个线程到另一个线程那么可以使用消息队列(见生产者/消费者)
JDK 中,join 的实现、Future
 
class GuardedObject {
	private Object response;
	private final Object lock = new Object();

	public Object get() {
		synchronized (lock) {
			// 条件不满足则等待
			while (response == null) {
				try {
					lock.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			return response;
		}
	}

	public void complete(Object response) {
		synchronized (lock) {
			// 条件满足,通知等待线程
			this.response = response;
			lock.notifyAll();
		}
	}
}

使用场景

public static void main(String[] args) {
	GuardedObject guardedObject = new GuardedObject();
	new Thread(() -> {
		try {
			// 子线程执行下载
			List<String> response = download();
			log.debug("download complete...");
			guardedObject.complete(response);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}).start();
	log.debug("waiting...");
	// 主线程阻塞等待
	Object response = guardedObject.get();
	log.debug("get response: [{}] lines", ((List<String>) response).size());
}
08:42:18.568 [main] c.TestGuardedObject - waiting...
08:42:23.312 [Thread-0] c.TestGuardedObject - download complete...
08:42:23.312 [main] c.TestGuardedObject - get response: [3] lines

 

带超时版 GuardedObject
class GuardedObject {

	private Object response;
	private final Object lock = new Object();

	public Object get(long millis) {
		synchronized (lock) {
			// 1) 记录最初时间
			long begin = System.currentTimeMillis();
			// 2) 已经经历的时间
			long timePassed = 0;
			while (response == null) {
				// 4) 假设 millis 是 1000,结果在 400 时唤醒了,那么还有 600 要等
				long waitTime = millis - timePassed;
				log.debug("waitTime: {}", waitTime);
				if (waitTime <= 0) {
					log.debug("break...");
					break;
				}
				try {
					lock.wait(waitTime);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				// 3) 如果提前被唤醒,这时已经经历的时间假设为 400
				timePassed = System.currentTimeMillis() - begin;
				log.debug("timePassed: {}, object is null {}", timePassed, response == null);
			}
			return response;
		}
	}

	public void complete(Object response) {
		synchronized (lock) {
			// 条件满足,通知等待线程
			this.response = response;
			log.debug("notify...");
			lock.notifyAll();
		}
	}
}

测试

public static void main(String[] args) {
	GuardedObjectV2 v2 = new GuardedObjectV2();
	new Thread(() -> {
		sleep(1);
		v2.complete(null);
		sleep(1);
		v2.complete(Arrays.asList("a", "b", "c"));
	}).start();
	Object response = v2.get(2500);
	if (response != null) {
		log.debug("get response: [{}] lines", ((List<String>) response).size());
	} else {
		log.debug("can't get response");
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值