同步模式之保护性暂停

同步模式之保护性暂停

  1. 定义

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

  2. 要点

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

在这里插入图片描述

package mythread.protectstop;

/**
 * @ClassName Stop
 * @Description TODO
 * @Author guangmingdexin
 * @Date 2020/11/8 15:47
 * @Version 1.0
 **/
public class ProtectedStop {

    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();
        }
    }

    /**
     * 这里如果用同步方法 则上锁的对象为 ProtectedStop的实例
     * 上锁的不是同一个对象,wait 方法会报错
     *
     * @return
     */
    public synchronized Object getResponse() {
        // 同步方法
        while (response == null) {
            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return response;
    }
}

ProtectedStop guardObject = new ProtectedStop();

        new Thread(() -> {
           // 模拟任务执行
            try {
                System.out.println("任务开始!");
                Thread.sleep(3 * 1000);
                System.out.println("任务完成,通知等待线程!");
                guardObject.complete(new Object());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t1").start();

        System.out.println("等待 ...");
        Object response = guardObject.get();

        System.out.println("接收到了结果!" + response.hashCode());
    }

执行结果

等待 ...
任务开始!
任务完成,通知等待线程!
接收到了结果!558638686

带超时版 GuardedObject

package mythread.protectstop;

import java.util.Date;

/**
 * @ClassName ProtectedStopV2
 * @Description TODO
 * @Author guangmingdexin
 * @Date 2020/11/8 16:42
 * @Version 1.0
 **/
public class ProtectedStopV2 {

    private Object response;

    private final Object lock = new Object();

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

    public void complete(Object response) {
        synchronized (lock) {
            this.response = response;
            lock.notifyAll();
        }
    }
}

ProtectedStopV2 v2 = new ProtectedStopV2();

        new Thread(() -> {
            try {
                Thread.sleep(1000);
                v2.complete(null);
                Thread.sleep(1000);
                v2.complete(new Object());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        // Object response = v2.get(3000);
        Object response = v2.get(1000);
        if(response != null) {
            System.out.println(new Date() + "获取到的" + response.hashCode());
        }else {
            System.out.println(new Date() + "获取失败!");
        }
    }


= null) {
            System.out.println(new Date() + "获取到的" + response.hashCode());
        }else {
            System.out.println(new Date() + "获取失败!");
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值