线程
程序员文章站
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)情况
- 调用join()和sleep()方法,sleep()时间结束或被打断,join()中断,IO完成都会回到Runnable状态,等待JVM的调度。
- 调用wait(),使该线程处于等待池(wait blocked pool),直到notify()/notifyAll(),线程被唤醒被放到锁定池(lock blocked pool ),释放同步锁使线程回到可运行状态(Runnable)
- 对Running状态的线程加同步锁(Synchronized)使其进入(lock blocked pool ),同步锁被释放进入可运行状态(Runnable)。
此外,在runnable状态的线程是处于被调度的线程,此时的调度顺序是不一定的。Thread类中的yield方法可以让一个running状态的线程转入runnable。
重点:
- 线程同步
- 线程间通信
- 线程死锁
- 线程控制:挂起、停止和恢复