欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

线程

程序员文章站 2022-06-21 10:44:17
...

首先要区分一下线程和进程

进程:进程是动态的,是程序执行的过程;我的理解就是,我打开王者荣耀,这就是启动一个进程,又打开网易云听歌,这又启动了一个进程。

线程:线程是在进程内部同时做的事情,比如我在王者里玩上路和别人对线,这个时候中路下路也在和敌方对线,这就是由多线程来实现的。

创建多线程有3种方式,分别是继承线程类,实现Runnable接口,匿名类

举个王者的例子,方便自己日后的复习和理解:

package com.xbj.demo;

//定义一个王者英雄类
public class WzHero {
    public String name;  //名字
    public int hp;  //血量
    public int atk; //攻击力

    public void attackHero(WzHero hero){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        hero.hp-=atk;   //每次进攻  血量减去攻击力
        System.out.format("%s对%s发起攻击了,%s血量变成%d;%n",name,hero.name,hero.name,hero.hp);
        if (hero.isDead()){
            System.out.println(hero.name+"死了");
        }
    }
    public boolean isDead(){
       return hp==0?true:false;
    }
}
package com.xbj.demo;

public class KillThread extends Thread {
    WzHero hero1;
    WzHero hero2;

    public KillThread(WzHero hero1,WzHero hero2){
        this.hero1=hero1;
        this.hero2=hero2;
    }

    public void run(){
        while(!hero2.isDead()){
            hero1.attackHero(hero2);
        }
    }


}
package com.xbj.demo;

public class TestThread {
    public static void main(String[] args) {
        WzHero hero1=new WzHero();
        hero1.name="亚瑟";
        hero1.hp=500;
        hero1.atk=100;

        WzHero hero2=new WzHero();
        hero2.name="鲁班七号";
        hero2.hp=300;
        hero2.atk=200;

        WzHero hero3=new WzHero();
        hero3.name="虞姬";
        hero3.hp=300;
        hero3.atk=200;

        WzHero hero4=new WzHero();
        hero4.name="程咬金";
        hero4.hp=600;
        hero4.atk=80;

        KillThread kt1=new KillThread(hero1,hero2);
        kt1.start();
        KillThread kt2=new KillThread(hero3,hero4);
        kt2.start();
    }
}

Thread.sleep(1000); 表示当前线程暂停1000毫秒 ,其他线程不受影响 
Thread.sleep(1000); 会抛出InterruptedException 中断异常,因为当前线程sleep的时候,有可能被停止,这时就会抛出 InterruptedException

start()方法是Thread类的方法,start()方法会使得该线程开始执行;java虚拟机会去调用该线程的run()方法。”

我在这里加一句kt1.join(),即表明在主线程中加入该线程。主线程就会等这个线程完成后才会执行下面的语句

  KillThread kt1=new KillThread(hero1,hero2);
        kt1.start();
        try {
            kt1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        KillThread kt2=new KillThread(hero3,hero4);
        kt2.start();

结果:

亚瑟对鲁班七号发起攻击了,鲁班七号血量变成200;
亚瑟对鲁班七号发起攻击了,鲁班七号血量变成100;
亚瑟对鲁班七号发起攻击了,鲁班七号血量变成0;
鲁班七号死了
虞姬对程咬金发起攻击了,程咬金血量变成400;
虞姬对程咬金发起攻击了,程咬金血量变成200;
虞姬对程咬金发起攻击了,程咬金血量变成0;
程咬金死了

确实是等kt1线程完成后,才继续执行主线程的

 

线程在Running的过程中可能会遇到阻塞(Blocked)情况

  1. 调用join()和sleep()方法,sleep()时间结束或被打断,join()中断,IO完成都会回到Runnable状态,等待JVM的调度。
  2. 调用wait(),使该线程处于等待池(wait blocked pool),直到notify()/notifyAll(),线程被唤醒被放到锁定池(lock blocked pool ),释放同步锁使线程回到可运行状态(Runnable)
  3. 对Running状态的线程加同步锁(Synchronized)使其进入(lock blocked pool ),同步锁被释放进入可运行状态(Runnable)。

此外,在runnable状态的线程是处于被调度的线程,此时的调度顺序是不一定的。Thread类中的yield方法可以让一个running状态的线程转入runnable。

重点:

  • 线程同步
  • 线程间通信
  • 线程死锁
  • 线程控制:挂起、停止和恢复
相关标签: 线程 Thread