考慮以下場景需求:
- A同學計算一個結果res
- B同學需要等待A同學的結果res
需要用到保護性暫停:一個線程等待另外一個線程的執行結果
這裏我們讓A,B同學關聯到一個類。
B同學一直等待A同學
import org.apache.log4j.Logger;
public class Demo1 {
private static Logger logger = Logger.getLogger(Demo1.class);
public static void main(String[] args) {
GuardedObject guardedObject=new GuardedObject();
new Thread(() -> {
try {//模擬計算花費了2s
logger.debug("A同學正在計算");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message Ares = new Message();//將答案算了出來
guardedObject.computeRes(Ares);
logger.debug("A同學計算完了,將答案傳給了B");
}, "A同學").start();
new Thread(()->{
Message res=guardedObject.getRes();
logger.debug("B同學得到了A的答案res");
logger.debug("於是B同學將答案: "+res.get()+"寫在了試卷上");
},"B同學").start();
}
}
class GuardedObject{
private Message res;
//返回題目
public Message getRes(){
synchronized (this){
while (res==null){//B一直在等待A
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return res;
}
}
//計算題目
public void computeRes(Message res){
synchronized (this) {
this.res = res;
this.notify();
}
}
}
class Message{//題目
String res;
public String get(){
res="這個題的答案是:xxxxxxxxxxx";
return res;
}
}
結果
如果A同學計算的時間很長,那B同學就要等那麼長嗎?
B同學也不傻,心想,我就等你一段時間,等不到我就不等了。
B同學等待一段時間
import org.apache.log4j.Logger;
import sun.awt.windows.ThemeReader;
public class Demo1 {
private static Logger logger = Logger.getLogger(Demo1.class);
public static void main(String[] args) {
GuardedObject guardedObject=new GuardedObject();
new Thread(()->{
try {
logger.debug("A同學正在計算");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message res=new Message();
guardedObject.computeRes(res);
logger.debug("A同學計算完了,將答案傳給B");
},"A").start();
new Thread(()->{
Message res = null;
try {
res=guardedObject.getRes(2005);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(res==null) logger.debug("我不等了");
else logger.debug("B得到了A的答案,答案是"+res.get());
},"B同學").start();
}
}
class GuardedObject{
private Message res;
//返回
public Message getRes(long timeout) throws InterruptedException {
synchronized (this){
long begin=System.currentTimeMillis();
long passedTime=0;
while (res==null){
if(timeout-passedTime<=0) break;//不等了,時間到了
this.wait(timeout-passedTime);//等待喚醒
passedTime=System.currentTimeMillis()-begin;
}
return res;
}
}
//計算答案res
public void computeRes(Message res){
synchronized (this) {
this.res = res;
this.notify();
}
}
}
class Message{
String res;
public String get(){
res="這個題的答案是:xxxxxxxxxxx";
return res;
}
}
將B的等待時間設置爲小於A的計算時間,
雖然A依然把答案傳給了B,但B也不能再處理了。