栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

同步模式之保护性暂停(Guarded Suspension)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

同步模式之保护性暂停(Guarded Suspension)

同步模式之保护性暂停(Guarded Suspension) 3.1使用背景

用在一个线程等待另一个线程的执行结果

3.2要点
  1. 一个线程需要得到另一个线程的结果,他们需要关联同一个GuardedObject

  2. 如果有结果不断从一个线程到另一个线程那么可以使用消息队列(见生产者/消费者)

  3. JDK 中,join 的实现、Future 的实现,采用的就是此模式

  4. 因为要等待另一方的结果,因此归类到同步模式

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LPTZ5lpd-1655016006794)(F:Java_notejava笔记img同步模式之保护性暂停.png)]

3.3 实现
package com.zjc.study.day611;

public class test1 {
    public static void main(String[] args) {
        GuardedObject guardedObject = new GuardedObject();
        new Thread(()->{
            guardedObject.getResponse();
        },"t1").start();
        new Thread(()->{
            guardedObject.setResponse("hello");
        },"t2").start();
    }

}

//1.定义一个类GuardedObject作为桥梁
class GuardedObject {
    //2.定义需要共享的资源
    private Object response;

    //3.get方法加锁
    public synchronized Object getResponse() {
        //4.如果response没有值就一直暂停
        while (response == null) {
            try {
                //4.暂停
                this.wait();
                System.out.println((String)response);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //5.如果response不是null就返回
        return response;
    }
    //6.set方法加锁
    public synchronized void setResponse(String s) {
        //7.给response赋值
        this.response = s;
        //8.唤醒等待的线程
        this.notify();
    }


}
3.4超时等待版GuardedObject
package com.zjc.study.day611;




import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;


@Slf4j
public class test1 {
    public static void main(String[] args)  {
        GuardedObject guardedObject = new GuardedObject();
        new Thread(() -> {
            Object response = guardedObject.getResponse(2000);
            System.out.println((String)response);
        }, "t1").start();

        new Thread(() -> {
            try {
                Thread.sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            guardedObject.setResponse("hello");
        }, "t2").start();
    }

}

//1.定义一个类GuardedObject作为桥梁
@Slf4j
class GuardedObject {
    //2.定义需要共享的资源
    private Object response;

    //3.get方法加锁
    public synchronized Object getResponse(long millis) {
        //统计起始时间
        long start = System.currentTimeMillis();
        //统计已经过去的时间
        long timepass = 0;
        //4.如果response没有值就一直暂停
        while (response == null) {
            try {
                //计算等待时间
                long waittime = millis - timepass;
                //判断是否超时
                if (waittime<=0){
                    break;
                }
                //4.暂停  传入等待参数
                this.wait(waittime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //每一花费的时间等于现在的系统时间减去开始时间
            timepass = System.currentTimeMillis() - start;
            log.info("timepass{}",timepass);
        }
        //5.如果response不是null就返回
        return response;
    }

    //6.set方法加锁
    public synchronized void setResponse(String s) {
        //7.给response赋值
        this.response = s;
        //8.唤醒等待的线程
        this.notify();
    }
}
3.5 多任务版 GuardedObject

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MbqSu8ay-1655016006797)(F:Java_notejava笔记img多任务GuardedObject.png)]

package com.zjc.study.day611;

import lombok.extern.slf4j.Slf4j;

import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

public class test2 {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 3; i++) {
            new People().start();
        }
        Thread.sleep(1000);
        for (Integer id : Mailboxes.getIds()) {
            new Postman(id, "内容" + id).start();
        }
    }
}


@Slf4j
class People extends Thread{
    @Override
    public void run() {
   
        NewGuardedObject guardedObject = Mailboxes.createGuardedObject();
        log.debug("开始收信 id:{}", guardedObject.getId());
        // 收信  如果时间范围内收到了就返回mail就有值 否则就是null
        Object mail = guardedObject.get(5000);
        
        log.debug("收到信 id:{}, 内容:{}", guardedObject.getId(), mail);
    }
}


@Slf4j
class Postman extends Thread {
    private int id;
    private String mail;

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

    @Override
    public void run() {
        //获得到该给那个放
        NewGuardedObject guardedObject = Mailboxes.getGuardedObject(id);
        log.debug("送信 id:{}, 内容:{}", id, mail);
        //这块才将内容放进去
        guardedObject.complete(mail);
    }
}

class Mailboxes {
    private static Map boxes = new Hashtable<>();

    private static int id = 1;

    // 产生唯一 id  需要加锁
    private static synchronized int generateId() {
        return id++;
    }

    
    public static NewGuardedObject getGuardedObject(int id) {
        return boxes.remove(id);
    }

    
    public static NewGuardedObject createGuardedObject() {
        NewGuardedObject go = new NewGuardedObject(generateId());
        boxes.put(go.getId(), go);
        return go;
    }

    
    public static Set getIds() {
        return boxes.keySet();
    }
}


class NewGuardedObject {

    // 标识 Guarded Object
    private int id;

    public NewGuardedObject(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    // 结果
    private Object response;

    // 获取结果
    // timeout 表示要等待多久 2000
    public Object get(long timeout) {
        synchronized (this) {
            // 开始时间 15:00:00
            long begin = System.currentTimeMillis();
            // 经历的时间
            long passedTime = 0;
            while (response == null) {
                // 这一轮循环应该等待的时间
                long waitTime = timeout - passedTime;
                // 经历的时间超过了最大等待时间时,退出循环
                if (timeout - passedTime <= 0) {
                    break;
                }
                try {
                    this.wait(waitTime); // 虚假唤醒 15:00:01
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 求得经历时间
                passedTime = System.currentTimeMillis() - begin; // 15:00:02 1s
            }
            return response;
        }
    }

    // 产生结果
    public void complete(Object response) {
        synchronized (this) {
            // 给结果成员变量赋值
            this.response = response;
            this.notifyAll();
        }
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/970409.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号