并发学习08--多线程同步模式之保护性暂停(wait暂停)

本文介绍了GuardedSuspension在Java中如何用于线程间通信,如t1等待t2线程结果,通过GuardedObject进行数据传递。讨论了JDK中的join()和Future实现原理,以及如何使用同步和wait/notify机制实现线程间的解耦和协作。
摘要由CSDN通过智能技术生成

Guarded Suspension: 用于一个线程等待另一个线程的执行结果。

1.t1线程需要等待t2线程的结果,让t1和t2关联同一个GuardedObject。

2.如果有结果不断的从t2到t1,那么可以使用消息队列(生产者 消费者)

3.JDK中,join()和Future的实现就是采用这个模式

4.将t2产生的结果放入GuardedObject的response中。t1从GuardedObject的response中拿到t2的值。

5.在t2产生结果的过程中t1需要用wait()来等待。

import lombok.extern.slf4j.Slf4j;

@Slf4j(topic = "TC8")
public class TC8 {
    public static void main(String[] args) {
        GuardedObject guardedObject = new GuardedObject();
        Thread thread1 = new Thread(() -> {
            log.debug("获取到结果:{}", guardedObject.getResponse(2000));
        });

        Thread thread2 = new Thread(() -> {
            guardedObject.setResponse("产生了结果");
        });

        thread1.start();
        thread2.start();
    }
}

class GuardedObject{
    private Object response;

    public Object getResponse(long timeOut) {
        synchronized (this){
            long startTime = System.currentTimeMillis();
            long spendTime = 0;
            while(response==null) {
                long waitTime = timeOut - spendTime; //防止虚假唤醒,唤醒时,object==null
                if (waitTime<=0) {
                    break;
                }
                try {
                    this.wait(waitTime); 
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                spendTime = System.currentTimeMillis()-startTime;
            }
            return response;
        }
    }

    public void setResponse(Object object) {
        synchronized (this) {
            this.response = object;
            this.notifyAll();
        }
    }

}

如果有多个线程一一对应传递消息,需要有个解耦类来管理各个GuardedObject.

t1,t3,t5给GuardedObject1.2.3传递结果;t0,t2,t4从GuardedObject1.2.3中拿到结果。

import lombok.extern.slf4j.Slf4j;

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

public class TC9 {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 3; i++) {
            new PersonTest().start();
        }
        Thread.sleep(1000);//等待生成GuardedObject,使postman循环得以执行

        for (Integer id : MailBoxTest.getIDs()) {
            new PostmanTest(id,"内容:"+id).start();
        }
    }
}
@Slf4j(topic = "PersonTest")
class PersonTest extends Thread{
    @Override
    public void run() {
        GuardedObjectTest guardedObjectTest = MailBoxTest.generateGuardedObject();
        log.debug("收信前ID:{}",guardedObjectTest.getId());
        Object result = guardedObjectTest.getResult(5000);
        log.debug("收信ID:{}, 收信内容:{}",guardedObjectTest.getId(),result);
    }
}

@Slf4j(topic = "PostmanTest")
class PostmanTest extends Thread{
    private int id;
    private String message;

    public PostmanTest(int id, String message) {
        this.id=id;
        this.message=message;
    }

    @Override
    public void run() {
        GuardedObjectTest object = MailBoxTest.getGuardedObjectByID(id);
        log.debug("发信id:{}, 发信内容:{}",id,message);
        object.setResult(message);
        
    }
}

class MailBoxTest{
    public static Map<Integer,GuardedObjectTest> boxes = new Hashtable<>();
    private static int id=1;

    public synchronized static int generateId() {
        return id++;
    }

    public static GuardedObjectTest generateGuardedObject() {
        GuardedObjectTest guardedObjectTest = new GuardedObjectTest(generateId());
        boxes.put(guardedObjectTest.getId(),guardedObjectTest);
        return guardedObjectTest;
    }

    public static GuardedObjectTest getGuardedObjectByID(int id) {
        return boxes.remove(id);
    }

    public static Set<Integer> getIDs() {
        return boxes.keySet();
    }
}

class GuardedObjectTest{
    private int id;
    private Object object;
    public GuardedObjectTest(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public Object getResult(long timeOut) {
        long start = System.currentTimeMillis();
        long spendTime=0;
        synchronized (this) {
            long waitTime = timeOut-spendTime;
            while(object==null){
                if (waitTime<=0) {
                    break;
                }
                try {
                    this.wait(waitTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                spendTime=System.currentTimeMillis()-start;
            }
            return object;
        }
    }

    public synchronized void setResult(Object object) {
        this.object = object;
        this.notifyAll();
    }
}

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值