多线程 常见的线程方法
sleep()线程暂停
Thread.sleep(1000); 表示当前线程暂停1000毫秒 ,其他线程不受影响
Thread.sleep(1000); 会抛出InterruptedException 中断异常,因为当前线程sleep的时候,有可能被停止,这时就会抛出 InterruptedException
package multiplethread;
public class TestThread {
public static void main(String[] args) {
Thread t1= new Thread(){
public void run(){
int seconds =0;
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.printf("已经玩了LOL %d 秒%n", seconds++);
}
}
};
t1.start();
}
}
join()加入到当前线程中
首先解释一下<mark>主线程</mark>的概念
所有进程,至少会有一个线程即主线程,即main方法开始执行,就会有一个看不见的主线程存在。
在执行t.join,即表明在主线程中加入该线程。
主线程会等待该线程结束完毕, 才会往下运行。
package charactor;
import java.io.Serializable;
public class Hero{
public String name;
public float hp;
public int damage;
public void attackHero(Hero h) {
try {
//为了表示攻击需要时间,每次攻击暂停1000毫秒
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;
}
}
package multiplethread;
import charactor.Hero;
public class TestThread {
public static void main(String[] args) {
final Hero gareen = new Hero();
gareen.name = "盖伦";
gareen.hp = 616;
gareen.damage = 50;
final Hero teemo = new Hero();
teemo.name = "提莫";
teemo.hp = 300;
teemo.damage = 30;
final Hero bh = new Hero();
bh.name = "赏金猎人";
bh.hp = 500;
bh.damage = 65;
final Hero leesin = new Hero();
leesin.name = "盲僧";
leesin.hp = 455;
leesin.damage = 80;
Thread t1= new Thread(){
public void run(){
while(!teemo.isDead()){
gareen.attackHero(teemo);
}
}
};
t1.start();
//代码执行到这里,一直是main线程在运行
try {
//t1线程加入到main线程中来,只有t1线程运行结束,才会继续往下走
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Thread t2= new Thread(){
public void run(){
while(!leesin.isDead()){
bh.attackHero(leesin);
}
}
};
//会观察到盖伦把提莫杀掉后,才运行t2线程
t2.start();
}
}
因为使用join将t1加入了主线程,主线程会最先执行,所以运行结果是先将线程t1执行结束,再执行t2.
setPriority()设置线程优先级
当线程处于竞争关系的时候,优先级高的线程会有更大的几率获得CPU资源
为了演示该效果,要把暂停时间去掉,多条线程各自会尽力去占有CPU资源
同时把英雄的血量增加100倍,攻击减低到1,才有足够的时间观察到优先级的演示
线程优先级的范围在1-10
如图可见,线程1的优先级是MAX_PRIORITY,所以它争取到了更多的CPU资源执行代码
package charactor;
import java.io.Serializable;
public class Hero{
public String name;
public float hp;
public int damage;
public void attackHero(Hero h) {
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;
}
}
package multiplethread;
import charactor.Hero;
public class TestThread {
public static void main(String[] args) {
final Hero gareen = new Hero();
gareen.name = "盖伦";
gareen.hp = 6160;
gareen.damage = 1;
final Hero teemo = new Hero();
teemo.name = "提莫";
teemo.hp = 3000;
teemo.damage = 1;
final Hero bh = new Hero();
bh.name = "赏金猎人";
bh.hp = 5000;
bh.damage = 1;
final Hero leesin = new Hero();
leesin.name = "盲僧";
leesin.hp = 4505;
leesin.damage = 1;
Thread t1= new Thread(){
public void run(){
while(!teemo.isDead()){
gareen.attackHero(teemo);
}
}
};
Thread t2= new Thread(){
public void run(){
while(!leesin.isDead()){
bh.attackHero(leesin);
}
}
};
t1.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
}
}
yield()临时暂停
yield中文翻译投降,起作用也差不多这个意思,当前线程,临时暂停,使得其他线程可以有更多的机会占用CPU资源,就像两个人抢吃的,甲,乙都想吃多点,打起来了,乙输了,就投降了,甲就吃的多,获取更多资源,但是不可能甲全吃了,乙还有不服的时候呢,就会加强锻炼,锻炼好了,就去再跟甲打架,来获取资源。这里跟sleep有明显的不同,sleep有固定的暂停时间,但是 yield只是临时认怂,没有固定时间。
package multiplethread;
import charactor.Hero;
public class TestThread {
public static void main(String[] args) {
final Hero gareen = new Hero();
gareen.name = "盖伦";
gareen.hp = 61600;
gareen.damage = 1;
final Hero teemo = new Hero();
teemo.name = "提莫";
teemo.hp = 30000;
teemo.damage = 1;
final Hero bh = new Hero();
bh.name = "赏金猎人";
bh.hp = 50000;
bh.damage = 1;
final Hero leesin = new Hero();
leesin.name = "盲僧";
leesin.hp = 45050;
leesin.damage = 1;
Thread t1= new Thread(){
public void run(){
while(!teemo.isDead()){
gareen.attackHero(teemo);
}
}
};
Thread t2= new Thread(){
public void run(){
while(!leesin.isDead()){
//临时暂停,使得t1可以占用CPU资源
Thread.yield();
bh.attackHero(leesin);
}
}
};
t1.setPriority(5);
t2.setPriority(5);
t1.start();
t2.start();
}
}
setDaemon()守护线程
守护线程的概念是: 当一个进程里,所有的线程都是守护线程的时候,结束当前进程。
举个实际的例子,就像我们打开一个LOL,我们打游戏的时候,后台会记录我们这一局输出多少,参团率多少等等,当本局游戏结束了,我们退出,返回主界面,那些记录我们参团率,输出的进行就相应的结束了。那些记录数据的线程就是守护进程,所以我们可以想一下,是不是当所有的进程都是这种记录的守护进程时,这个程序就没有运行的必要了,所以就结束了当前的进程。
守护线程通常会被用来做日志,性能统计等工作。
package multiplethread;
public class TestThread {
public static void main(String[] args) {
Thread t1= new Thread(){
public void run(){
int seconds =0;
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.printf("已经玩了LOL %d 秒%n", seconds++);
}
}
};
t1.setDaemon(true);
t1.start();
}
}
我们运行,会发现直接运行结束,因为进程里,所有的线程都是守护线程,所以结束当前进程。