zoukankan      html  css  js  c++  java
  • 线程交互

    线程交互

      盖伦持续掉血,但是血量到达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();
        }
    
    }

      效果

  • 相关阅读:
    SVGEditor
    SVG六基本元素
    SVG在网页中的四种使用方式
    Chrome中java因过期而遭到阻止
    Weblogic常见故障常:JDBC Connection Pools
    MyBatis java.sql.SQLSyntaxErrorException: ORA-00911: 无效字符
    MYBATIS 无效的列类型: 1111
    [MyBatis]mapperLocations属性通配符的使用
    secureCRT自动化脚本
    google protocol buffer的原理和使用(四)
  • 原文地址:https://www.cnblogs.com/HelloM/p/14409334.html
Copyright © 2011-2022 走看看