• 线程交互


    线程交互

      盖伦持续掉血,但是血量到达1的时候,不能继续掉了,因为血量不能为负。只有等待回复血量,再进行减血操作,这个时候就有两个线程在操作这个英雄的hp,这两个线程操作的过程就是交互。减血线程到1时,等待加血线程加血wait,加血之后,唤醒减血线程notify。这样完成两个线程的交互。

    交互流程图

      wait是线程等待的意思,将当前线程推出cpu,把唤醒(notify)的线程放入cpu执行完,然后再执行之前wait的线程。如果notifyall唤醒所有线程,那么这所有唤醒的线程,就进行抢占cpu,谁抢到谁去执行。

    示例代码

      在具体的业务代码中,去指定那个方法该等待wait,哪个该notify唤醒。Hero.java

    package com.thread.thread15;
    
    public class Hero {
        public String name;   //英雄名字
        public float hp;   //血量
        public int damage;   //攻击力
    
        //回复血量
        public synchronized void recover() {
            hp = hp + 1;
            System.out.printf("%s 回血一点后, %s的血量是%.0f%n", name, name, hp);
            //通知那些等待的this对象上的线程  可以醒过来了  如第20行  等待着减血线程苏醒过来
            this.notify();
        }
    
        //减少血量
        public synchronized void hurt() {
            if(hp==1) {
                try {
                    //让占有this的减血线程 暂时释放对this的占有  并等待
                    this.wait();
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            hp = hp - 1;
            System.out.printf("%s 减血1点 ,减少血后, %s的血量是%.0f%n", name, name, hp );
        }
    
        //攻击手段
        public void attackHero(Hero h) {
            h.hp -= damage;   //每次攻击 英雄都会损失相应血量
            //%s对应的字符串变量
            //%.f 血量float
            System.out.printf("%s 正在攻击 %s, %s的血变成了 %.0f%n", name, h.name, h.name, h.hp);
            if(h.isDead()) {
                System.out.println(h.name + "死了!");
            }
        }
    
        //判断英雄是否死亡
        public boolean isDead(){
            return 0>=hp?true:false; // 如果血量 小于0  则isDead=true   血量大于0  则isDead=false 没有死
        }
    }

      测试类中,创建两个线程启动。当然在线程内部,可以用具体的代码逻辑来代替线程的交互操作,但是会消耗大量的cpu,所以使用这样的交互过程

    package com.thread.thread15;
    
    public class TestThread {
        public static void main(String[] args) {
            final Hero gareen = new Hero();
            gareen.name = "盖伦";
            gareen.hp = 100;
    
            Thread t1 = new Thread() {
                public void run() {
                    while(true) {
                        //因为减少血量更快  所以盖伦的血量迟早会到达1
                        //使用while循环判断是否1  如果1的话不停的循环
                        //直到加血线程回复了血量
    //                    while(gareen.hp == 1) {
    //                        continue;
    //                    }
                        gareen.hurt();
                      //  System.out.printf("t1 为 %s 减血1点,减少血后,%s的血量是%.0f%n", gareen.name, gareen.name,gareen.hp);
    
                        try {
                            Thread.sleep(10);
                        }catch(InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            t1.start();
    
            Thread t2 = new Thread(){
                public void run() {
                    while(true) {
                        gareen.recover();
                       // System.out.printf("t2 为%s回血1点,增加血量后,%s的血量是%.0f%n", gareen.name, gareen.name, gareen.hp);
                        try{
                            Thread.sleep(100);
                        }catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            t2.start();
        }
    
    }

      效果

  • 相关阅读:
    HTTP学习三:HTTPS
    JavaScript判断变量的类型
    用JS创建10个<a>标签,点击的时候弹出来对应的序号
    【工具】根据后端提供的swagger生成前端的axios请求配置文件/api
    JavaScript正则表达式-零宽断言
    JavaScript中数组去重、对象去重的方法
    收集的无版权图片网站(欢迎补充)
    css 清除浮动
    JavaScript+CSS+HTML 编写手风琴效果
    Mac定制终端:iTerm2 + zsh + powerline
  • 原文地址:https://www.cnblogs.com/HelloM/p/14409334.html
Copyright © 2020-2023  润新知