多线程
一.启动一个线程
-
首先要理解进程(Processor)和线程(Thread)的区别
进程:启动一个LOL.exe就叫一个进程。 接着又启动一个DOTA.exe,这叫两个进程。
线程:线程是在进程内部同时做的事情,比如在LOL里,有很多事情要同时做,比如”盖伦” 击杀“提莫”,同时“赏金猎人”又在击杀“盲僧”,这就是由多线程来实现的。 -
使用多线程,就可以做到盖伦在攻击提莫的同时,赏金猎人也在攻击盲僧
设计一个类KillThread 继承Thread,并且重写run方法
启动线程办法: 实例化一个KillThread对象,并且调用其start方法
就可以观察到 赏金猎人攻击盲僧的同时,盖伦也在攻击提莫
I.创建多线程————继承线程类(方式)
Hero类
package Thread;
public class Hero {
public String name;
public int hp;
public int damage;
public Hero(String name,int hp,int damage)
{
this.name=name;
this.hp=hp;
this.damage=damage;
}
public boolean isDead()
{
return hp<=0;
}
public void attack(Hero h)
{
try{
Thread.sleep(1000);
}catch(InterruptedException e)
{
e.printStackTrace();
}
if(h.hp-damage>0)
{
h.hp-=damage;
System.out.println(h.name+"的hp减少了"+damage+"点,剩余hp为"+h.hp);
}
else
{
h.hp=0;
System.out.println(h.name+"死了");
}
}
}
testThread类
package Thread;
public class testThread{
public static void main(String[] args) {
Hero gareen=new Hero("gareen",616,50);
Hero temmo=new Hero("temmo",300,30);
Hero mf=new Hero("mf",500,65);
Hero leesin=new Hero("leesin",455,80);
killThread k1=new killThread(gareen,temmo);
k1.start();
killThread k2=new killThread(mf,leesin);
k2.start();
}
}
killThread
package Thread;
public class killThread extends Thread{
private Hero h1;
private Hero h2;
public killThread(Hero h1,Hero h2)
{
this.h1=h1;
this.h2=h2;
}
public void run()
{
while(h1.isDead()==false&&h2.isDead()==false)
{
if(h1.isDead()==false) h1.attack(h2);
if(h2.isDead()==false) h2.attack(h1);
}
}
}
II.创建多线程-实现Runnable接口(方式)
- 创建类Battle,实现Runnable接口
启动的时候,首先创建一个Battle对象,然后再根据该battle对象创建一个线程对象,并启动
Battle battle1 = new Battle(gareen,teemo);
new Thread(battle1).start();
- battle1 对象实现了Runnable接口,所以有run方法,但是直接调用run方法,并不会启动一个新的线程。
必须,借助一个线程对象的start()方法,才会启动一个新的线程。
所以,在创建Thread对象的时候,把battle1作为构造方法的参数传递进去,这个线程启动的时候,就会去执行battle1.run()方法了。
package Thread;
public class Battle implements Runnable{
private Hero h1;
private Hero h2;
public Battle(Hero h1,Hero h2)
{
this.h1=h1;
this.h2=h2;
}
public void run(){
while(h1.isDead()==false&&h2.isDead()==false)
{
if(h1.isDead()==false) h1.attack(h2);
if(h2.isDead()==false) h2.attack(h1);
}
}
}
package Thread;
public class testThread{
public static void main(String[] args) {
Hero gareen=new Hero("gareen",616,50);
Hero temmo=new Hero("temmo",300,30);
Hero mf=new Hero("mf",500,65);
Hero leesin=new Hero("leesin",455,80);
Battle b1=new Battle(gareen,temmo);new Thread(b1).start();
Battle b2=new Battle(mf,leesin);new Thread(b2).start();
}
}
III.匿名内部类
- 使用匿名类,继承Thread,重写run方法,直接在run方法中写业务代码
匿名类的一个好处是可以很方便的访问外部的局部变量。
前提是外部的局部变量需要被声明为final。(JDK7以后就不需要了)
package Thread;
public class testThread{
public static void main(String[] args) {
Hero gareen=new Hero("gareen",616,50);
Hero temmo=new Hero("temmo",300,30);
Hero mf=new Hero("mf",500,65);
Hero leesin=new Hero("leesin",455,80);
Thread t1=new Thread(){
public void run()
{
while(temmo.isDead()==false&&gareen.isDead()==false)
{
if(temmo.isDead()==false) temmo.attack(gareen);
if(gareen.isDead()==false) gareen.attack(temmo);
}
}
};
t1.start();
//接下来展示一种lambda形式的匿名内部类写法
Thread t2= new Thread(() -> {
while(mf.isDead()==false&&leesin.isDead()==false)
{
if(mf.isDead()==false) mf.attack(leesin);
if(leesin.isDead()==false) leesin.attack(mf);
}
});
t2.start();
}
}
IV.创建多线程的三种方式
把上述3种方式再整理一下:
- 继承Thread类
- 实现Runnable接口
- 匿名类的方式
注: 启动线程是start()方法,run()并不能启动一个新的线程