线程交互

线程交互

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

}

  效果

 

posted @ 2021-02-17 18:02  上天安排的最大嘛!  阅读(47)  评论(0编辑  收藏  举报