Java中保护性暂停设计模式

         保护性暂停设计模式是一种在多线程编程中常用的线程同步模式,它允许线程在满足特定条件之前暂停执行,从而避免不必要的资源消耗和竞争条件。

package com.juc.init;

import java.util.Collection;
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 设计模式-保护性暂停
 */
public class GuardedObjectDemo {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 3; i++) {
            new Person().start();
        }
        Thread.sleep(1000);
        for (Integer id : MailBoxes.getIds()) {
            new Postman(id,"这是一份"+id).start();
        }
    }
}
// 邮局
class MailBoxes {
    private static Map<Integer, GuardedObject> boxes = new Hashtable<>(); // 线程安全的
    private static int id = 1;

    private static synchronized int genId() { // id原子性自增,对类对象加锁
        return id++;
    }

    public static GuardedObject getGuardedObject(Integer id) {
        return boxes.remove(id); // 获取并删除
    }

    public static GuardedObject createGuardedObject() {
        int id = genId();
        GuardedObject guardedObject = new GuardedObject(id);
        boxes.put(id, guardedObject);
        return guardedObject;
    }

    public static Collection<Integer> getIds() {
        return boxes.keySet();
    }
}
//收件人
class Person extends Thread {
    @Override
    public void run() {
        GuardedObject guardedObject = MailBoxes.createGuardedObject();
        System.out.println("开始收信:id:" + guardedObject.getId());
        Object mail = guardedObject.get(); // 阻塞等待
        System.out.println("收到信了:" + mail);
    }
}
// 寄件人(送件)
class Postman extends Thread {
    private Integer id; // 那个柜子
    private String mail; // 邮件

    public Postman(Integer id, String mail) {
        this.id = id;
        this.mail = mail;
    }

    @Override
    public void run() {
        GuardedObject guardedObject = MailBoxes.getGuardedObject(id);
        System.out.println("邮递员把邮件放到:" + id + "号柜子,信件内容:" + mail);
        guardedObject.complete(mail);

    }
}
// 邮件柜子
class GuardedObject {
    private Object response;
    private Integer id;

    public GuardedObject(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public Object get() {
        synchronized (this) {
            while (response == null) {
                try {
                    System.out.println("等待数据中……");
                    this.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            return response;
        }
    }

    public void complete(Object resp) {
        synchronized (this) {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            this.response = resp;
            this.notifyAll();
        }
    }

}

通过以上代码设计场景,每一个人(Person)都是一个等待信件的线程,在main方法中创建了三个人去等待信件,同过调用邮局的createGuardedObject指定柜子,隔了一秒后,派三个邮递员(Postman)去送邮局需要送的信件,也就是收件人一开始监听的信件,这个信件放到了GuardedObject(小柜子)中,而邮局中每一个GuardedObject又对于了一个编号,也就是代码中的id。接着分析GuardedObject中的get与complete方法,get方法是用于收件人获取信件内容的途径,通过while(response == null)的循环去等待信件到达,留个问题while改成if可以不可以?,而complete方法是Postman用来放置信件的方法,当放完信件之后调用notifyAll方法,就是向外界广播:“又新的邮件送到啦!”。所以为什么get方法中用的是while循环而不是if,是因为这里唤醒了所有的线程,但是这些线程不一定是真正的收件人,所以要通过while循环直至真的收件人过来取值。

所以最后运行结果是这样的:

收件人指定对应的柜子编号,由Postman通过complete将信件送达 ,而且是一个收件人就对应着一个Postman,也就是这个设计模式是一个一对一的关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心与酒馆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值