行业资讯 2025年08月6日
0 收藏 0 点赞 336 浏览 3790 个字
摘要 :

文章目录 同步模式 保护性暂停 单任务版 多任务版 顺序输出 交替输出 同步模式 保护性暂停 单任务版 Guarded Suspension,用在一个线程等待另一个线程的执行结果 ……




  • 同步模式
    • 保护性暂停
      • 单任务版
      • 多任务版
    • 顺序输出
    • 交替输出

    同步模式

    保护性暂停

    单任务版

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

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

    public static void main(String[] args) {
        GuardedObject object = new GuardedObjectV2();
        new Thread(() -> {
            sleep(1);
            object.complete(Arrays.asList("a", "b", "c"));
        }).start();
        
        Object response = object.get(2500);
        if (response != null) {
            log.debug("get response: [{}] lines", ((List<String>) response).size());
        } else {
            log.debug("can't get response");
        }
    }
    
    class GuardedObject {
        private Object response;
        private final Object lock = new Object();
    
        //获取结果
        //timeout :最大等待时间
        public Object get(long millis) {
            synchronized (lock) {
                // 1) 记录最初时间
                long begin = System.currentTimeMillis();
                // 2) 已经经历的时间
                long timePassed = 0;
                while (response == null) {
                    // 4) 假设 millis 是 1000,结果在 400 时唤醒了,那么还有 600 要等
                    long waitTime = millis - timePassed;
                    log.debug("waitTime: {}", waitTime);
                    //经历时间超过最大等待时间退出循环
                    if (waitTime <= 0) {
                        log.debug("break...");
                        break;
                    }
                    try {
                        lock.wait(waitTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 3) 如果提前被唤醒,这时已经经历的时间假设为 400
                    timePassed = System.currentTimeMillis() - begin;
                    log.debug("timePassed: {}, object is null {}",
                            timePassed, response == null);
                }
                return response;
            }
        }
    
        //产生结果
        public void complete(Object response) {
            synchronized (lock) {
                // 条件满足,通知等待线程
                this.response = response;
                log.debug("notify...");
                lock.notifyAll();
            }
        }
    }
    
    多任务版

    多任务版保护性暂停:

    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(topic = "c.People")
    class People extends Thread{
        @Override
        public void run() {
            // 收信
            GuardedObject guardedObject = Mailboxes.createGuardedObject();
            log.debug("开始收信i d:{}", guardedObject.getId());
            Object mail = guardedObject.get(5000);
            log.debug("收到信id:{},内容:{}", guardedObject.getId(),mail);
        }
    }
    
    class Postman extends Thread{
        private int id;
        private String mail;
        //构造方法
        @Override
        public void run() {
            GuardedObject guardedObject = Mailboxes.getGuardedObject(id);
            log.debug("开始送信i d:{},内容:{}", guardedObject.getId(),mail);
            guardedObject.complete(mail);
        }
    }
    
    class  Mailboxes {
        private static Map<Integer, GuardedObject> boxes = new Hashtable<>();
        private static int id = 1;
    
        //产生唯一的id
        private static synchronized int generateId() {
            return id++;
        }
    
        public static GuardedObject getGuardedObject(int id) {
            return boxes.remove(id);
        }
    
        public static GuardedObject createGuardedObject() {
            GuardedObject go = new GuardedObject(generateId());
            boxes.put(go.getId(), go);
            return go;
        }
    
        public static Set<Integer> getIds() {
            return boxes.keySet();
        }
    }
    class GuardedObject {
        //标识,Guarded Object
        private int id;//添加get set方法
    }
    

    顺序输出

    顺序输出 2 1

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (true) {
                //try { Thread.sleep(1000); } catch (InterruptedException e) { }
                // 当没有许可时,当前线程暂停运行;有许可时,用掉这个许可,当前线程恢复运行
                LockSupport.park();
                System.out.println("1");
            }
        });
        Thread t2 = new Thread(() -> {
            while (true) {
                System.out.println("2");
                // 给线程 t1 发放『许可』(多次连续调用 unpark 只会发放一个『许可』)
                LockSupport.unpark(t1);
                try { Thread.sleep(500); } catch (InterruptedException e) { }
            }
        });
        t1.start();
        t2.start();
    }
    

    交替输出

    连续输出 5 次 abc

    public class day2_14 {
        public static void main(String[] args) throws InterruptedException {
            AwaitSignal awaitSignal = new AwaitSignal(5);
            Condition a = awaitSignal.newCondition();
            Condition b = awaitSignal.newCondition();
            Condition c = awaitSignal.newCondition();
            new Thread(() -> {
                awaitSignal.print("a", a, b);
            }).start();
            new Thread(() -> {
                awaitSignal.print("b", b, c);
            }).start();
            new Thread(() -> {
                awaitSignal.print("c", c, a);
            }).start();
    
            Thread.sleep(1000);
            awaitSignal.lock();
            try {
                a.signal();
            } finally {
                awaitSignal.unlock();
            }
        }
    }
    
    class AwaitSignal extends ReentrantLock {
        private int loopNumber;
    
        public AwaitSignal(int loopNumber) {
            this.loopNumber = loopNumber;
        }
        //参数1:打印内容  参数二:条件变量  参数二:唤醒下一个
        public void print(String str, Condition condition, Condition next) {
            for (int i = 0; i < loopNumber; i++) {
                lock();
                try {
                    condition.await();
                    System.out.print(str);
                    next.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    unlock();
                }
            }
        }
    }
    

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/10412.html

管理员

相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

988
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

465
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

348
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

456
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

517
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

832
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号