java線程-保護性暫停(wait,notify實現)

考慮以下場景需求:

  1. A同學計算一個結果res
  2. 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也不能再處理了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章