创建多线程

多线程概念


  进程:当点开英雄联盟的时候,我们就启动了一个进程。如果这时候又打开QQ音乐,那我们就是又开启了一个进程。

  线程:线程是进程内部同时在做的事情,比如在英雄联盟游戏中,"盖伦正在击杀提莫",同一时刻"赏金猎人又在击杀盲僧",这个时候盖伦击杀提莫这件事就是一个线程,在这里两个线程在做事情,就统称多线程。

 

顺序执行线程


   1、描述两件事情,并没有同时发生,只是一件事情发生完了以后,另一件事情才开始。Hero类

package com.thread;

public class Hero {
    public String name;
    public float hp;

    public int damage;

    public void attackHero(Hero h) {
        try {
            //为了表示攻击需要时间   每次攻击暂停1秒
            Thread.sleep(1000);
        }catch(InterruptedException e) {
            e.printStackTrace();
        }
        h.hp -= damage;
        System.out.format("%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=false
    }
}

  2、顺序执行两个模拟的线程,TestThread

package com.thread;

public class TestThread {
    public static void main(String[] args) {
        Hero gareen = new Hero();
        gareen.name = "盖伦";
        gareen.hp = 616;
        gareen.damage = 50;

        Hero teemo = new Hero();
        teemo.name = "提莫";
        teemo.hp = 300;
        teemo.damage = 30;

        Hero bh = new Hero();
        bh.name = "赏金猎人";
        bh.hp = 500;
        bh.damage = 65;

        Hero leesin = new Hero();
        leesin.name = "盲僧";
        leesin.hp = 445;
        leesin.damage = 80;

        //盖伦攻击提莫
        while(!teemo.isDead()) { //提莫的是否死亡   false就是没死   !false=true      那么盖伦继续攻击 直到提莫没了
            gareen.attackHero(teemo);   //盖伦攻击提莫
        }

        //赏金猎人攻击盲僧
        while(!leesin.isDead()) {
            bh.attackHero(leesin);  //赏金猎人攻击盲僧
        }
    }
}

  效果

 

 创建线程


   三种方式:继承Thread类,实现Runnable接口,内部类

  1、继承Thread类。Thread类实现了Runnable接口,这里run方法重写了Runnable中的run方法,重新定义算法,这个算法描述此线程在做什么事情。

package com.thread.thread1;

import com.thread.Hero;

//这里继承Thread   Thread本质也是实现Runnable接口    THread重写run方法
public class KillThread extends Thread {
    private Hero h1;  //做两个英雄出来
    private Hero h2;

    public KillThread(Hero h1, Hero h2) {  //把两个英雄放入killTHread中
        this.h1 = h1;
        this.h2 = h2;
    }

    public void run() {   //这里继承 重新声明了run方法 没有用原本的
        while(!h2.isDead()) {
            h1.attackHero(h2);
        }
    }
}

  启动线程测试,这里传入的对象作为参数,传递到线程类中的构造方法,实例出来的线程对象,调用其父类Thread的start方法,执行该线程的run函数。

package com.thread.thread1;
import com.thread.Hero;
public class TestT {
    public static void main(String[] args) {

        Hero gareen = new Hero();
        gareen.name = "盖伦";
        gareen.hp = 616;
        gareen.damage = 50;

        Hero teemo = new Hero();
        teemo.name = "提莫";
        teemo.hp = 300;
        teemo.damage = 30;

        Hero bh = new Hero();
        bh.name = "赏金猎人";
        bh.hp = 500;
        bh.damage = 65;

        Hero leesin = new Hero();
        leesin.name = "盲僧";
        leesin.hp = 455;
        leesin.damage = 80;

        //创建一个线程  里面盖伦和提莫在打架
        KillThread killThread1 = new KillThread(gareen, teemo);
        killThread1.start();   //启动线程  执行Thread中start方法   我们自己声明的线程类没有这个start方法


        KillThread killThread2 = new KillThread(bh, leesin);   //再创建一个线程
        killThread2.start();   //第二个线程启动

        //总结 两个线程互不影响
    }
}

  2、实现Runnable接口,实现接口,实现的是接口内的方式,override。

package com.thread.thread2;
import com.thread.Hero;
public class Battle implements Runnable{

    private Hero h1;
    private Hero h2;

    public Battle(Hero h1, Hero h2) {
        this.h1 = h1;
        this.h2 = h2;
    }

    @Override
    public void run() {
        while(!h2.isDead()) {
            h1.attackHero(h2);
        }
    }
}

  编写测试类,重新new了一个线程,将自己实现的类的实例对象传入线程中,然后启动线程的start方法

package com.thread.thread2;

import com.thread.Hero;

public class TestT {
    public static void main(String[] args) {
        Hero gareen = new Hero();
        gareen.name = "盖伦";
        gareen.hp = 616;
        gareen.damage = 50;

        Hero teemo = new Hero();
        teemo.name = "提莫";
        teemo.hp = 300;
        teemo.damage = 30;

        Hero bh = new Hero();
        bh.name = "赏金猎人";
        bh.hp = 500;
        bh.damage = 65;

        Hero leesin = new Hero();
        leesin.name = "盲僧";
        leesin.hp = 455;
        leesin.damage = 80;

        //创建一个实现线程类的类的对象  但是这个对象没有start方法
        Battle battle1 = new Battle(gareen, teemo);

        new Thread(battle1).start();   //我们就将这个对象 传到Thread中 调用其中的start方法

        Battle battle2 = new Battle(bh, leesin);
        new Thread(battle2).start();

        //两种创建线程的方法
        //1、继承Thread方法   直接声明run方法  然后调用父类Thread的start启动线程
        //2、实现Runnable接口   重写run方法  实例化该类,得到对象传入Thread构造方法中  调用其中的start方法 启动线程
    }
}

  3、编写内部类,类中创建线程,调用该线程对象的start方法。补充:内部类可以调用外部类的变量

package com.thread.thread3;

import com.thread.Hero;

public class TestT {
    public static void main(String[] args) {
        Hero gareen = new Hero();
        gareen.name = "盖伦";
        gareen.hp = 616;
        gareen.damage = 50;

        Hero teemo = new Hero();
        teemo.name = "提莫";
        teemo.hp = 300;
        teemo.damage = 30;

        Hero bh = new Hero();
        bh.name = "赏金猎人";
        bh.hp = 500;
        bh.damage = 65;

        Hero leesin = new Hero();
        leesin.name = "盲僧";
        leesin.hp = 455;
        leesin.damage = 80;

        //匿名类
        Thread t1 = new Thread() {   //匿名类  创建一个匿名对象
            public void run() {   //重新实现它的run方法

                //匿名类中用到的外部的局部变量teemo 必须把teemo声明成final
                //但是jdk7后  就不用加上final了
                while(!teemo.isDead()) {
                    gareen.attackHero(teemo);
                }
            }
        };
        t1.start();  //调用该内部类的方法  启动线程对象

        Thread t2 = new Thread() {
            public void run() {
                while(!leesin.isDead()) {
                    bh.attackHero(leesin);
                }
            }
        };
        t2.start();  //启动第二个线程
    }
}

总结


   线程的创建要么是创建本质都是实例Thread类,重写run方法(这个run方法是runnable接口中的),执行Thread类中的start方法启动线程。Thread类是实现Runnable接口的。

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