4.13多线程--模式之保护性暂停

定义

即 Guarded Suspension,用在一个线程等待另一个线程的执行结果
要点:

  • 有一个结果需要从一个线程传递到另一个线程,让他们关联同一个 GuardedObject
  • 如果有结果不断从一个线程传递到另一个线程,那么可以使用消息队列(生产者-消费者模式)
  • JDK 中,join 的实现、Future 的实现,采用的就是保护性暂停模式
  • 因为要等待另一个线程的结果,因此归类到同步模式


    image.png
/**
 * 1、两个线程之间交互结果
 * 2、join 方式,必须等待另一个线程执行结束
 * 3、join 方式,等待结果的变量必须是全局的;保护性暂停方式 List list = (List)guardedObject.get(); List list = Downloader.download();都是局部变量;
 **/
public class Demo1 {
    public static void main(String[] args) {
        GuardedObject guardedObject = new GuardedObject();
        new Thread(()->{
            System.out.println("线程 t1 等待结果");
            List list = (List)guardedObject.get();
            System.out.println("线程 t1 结果大小为:" + list.size());
        },"t1").start();

        new Thread(()->{
            System.out.println("线程 t2 执行下载");
            List list = Downloader.download();
            guardedObject.complete(list);
        },"t2").start();
    }
}

class GuardedObject {
    private Object response;

    //获得
    public Object get() {
        synchronized (this){
            while(response == null){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return response;
        }
    }

    //生成
    public void complete(Object response){
        synchronized (this){
            this.response = response;
            this.notifyAll();
        }
    }
}

增加超时

/**
 * 1、增加超时
 **/
public class Demo2 {
    static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
    public static void main(String[] args) {
        GuardedObject2 guardedObject = new GuardedObject2();
        new Thread(()->{
            System.out.println(sdf.format(new Date()) + " 线程 t1 等待结果");
            Object obj = guardedObject.get(2000);
            System.out.println(sdf.format(new Date()) + " 线程 t1 结果为:" + obj);
        },"t1").start();

        new Thread(()->{
            System.out.println(sdf.format(new Date()) + " 线程 t2 执行下载");
            try {
                Thread.sleep(1000);// 1. 等待时间内 返回结果,唤醒
//                Thread.sleep(3000);// 2. 超过等待时间 返回结果,唤醒
//                Thread.sleep(1000);// 3. 等待时间内 返回结果,不返回对象,虚假唤醒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            guardedObject.complete(new Object());// 1 2
//            guardedObject.complete(null);// 3
        },"t2").start();
    }
}
// 增加超时
class GuardedObject2 {
    private Object response;

    /**
     *  获得
     * @param timeout 等待最长时间
     * @return
     */
    public Object get(long timeout) {
        synchronized (this){
            // 开始执行时间
            long begin = System.currentTimeMillis();
            // 执行了多长时间
            long passedTime = 0;
            while(response == null){
                // 需要等待时间
                long waitTime = timeout - passedTime;
                if(waitTime <= 0){// 等待超过最长时间 退出循环
                    break;
                }
                try {
                    this.wait(waitTime);// 不用 timeout ,防止虚假唤醒 浪费时间
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                passedTime = System.currentTimeMillis() - begin;
            }
            return response;
        }
    }

    //生成
    public void complete(Object response){
        synchronized (this){
            this.response = response;
            this.notifyAll();
        }
    }
}

输出结果:

结果1 :
21:57:55 线程 t1 等待结果
21:57:55 线程 t2 执行下载
21:57:56 线程 t1 结果为:java.lang.Object@381d618c
结果2:
21:58:36 线程 t1 等待结果
21:58:36 线程 t2 执行下载
21:58:38 线程 t1 结果为:null
结果3:
21:59:55 线程 t2 执行下载
21:59:55 线程 t1 等待结果
21:59:57 线程 t1 结果为:null

你可能感兴趣的:(4.13多线程--模式之保护性暂停)