[TOC]
# 常见方法
| 关键字 | 简介 |
|---|---|
| sleep | 当前线程暂停 |
| join| 加入到当前线程中|
| setPriority| 线程优先级|
| yield| 临时暂停|
| setDaemon | 守护线程 |
# 当前线程暂停
Thread.sleep(1000); 表示当前线程暂停1000毫秒 ,其他线程不受影响
Thread.sleep(1000); 会抛出InterruptedException 中断异常,因为当前线程sleep的时候,有可能被停止,这时就会抛出 InterruptedException
```
package multiplethread;
public class TestThread5 {
public static void main(String[] args) {
Thread t = new Thread(){
@Override
public void run(){
int seconds = 0;
while (true) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.printf("已经玩了LOL %d 秒%n", seconds++);
}
}
};
t.start();
}
}
```
# 加入到当前线程中
首先解释一下主线程的概念
所有进程,至少会有一个线程即主线程,即main方法开始执行,就会有一个看不见的主线程存在。
在42行执行t.join,即表明在主线程中加入该线程。
主线程会等待该线程结束完毕, 才会往下运行。
```
package multiplethread;
import charactor.Hero;
public class TestThread6 {
public static void main(String[] args) {
Hero garen = new Hero();
garen.name = "盖伦";
garen.hp = 616;
garen.damage = 50;
Hero temmo = new Hero();
temmo.name = "提莫";
temmo.hp = 300;
temmo.damage = 30;
Hero bh = new Hero();
bh.name = "赏金猎人";
bh.hp = 500;
bh.damage = 65;
Hero lessin = new Hero();
lessin.name = "盲僧";
lessin.hp = 455;
lessin.damage = 80;
Thread t1 = new Thread() {
@Override
public void run() {
while (!temmo.isDead()) {
garen.attackHero(temmo);
}
}
};
t1.start();
//代码执行到这里,一直是main线程在运行
try {
//t1线程加入到main线程中来,只有t1线程运行结束,才会继续往下走
t1.join();
} catch (Exception e) {
e.printStackTrace();
}
Thread t2 = new Thread() {
@Override
public void run() {
while (!lessin.isDead()) {
bh.attackHero(lessin);
}
}
};
//会观察到盖伦把提莫杀掉后,才运行t2线程
t2.start();
}
}
```
# 线程优先级
当线程处于竞争关系的时候,优先级高的线程会有更大的几率获得CPU资源
为了演示该效果,要把暂停时间去掉,多条线程各自会尽力去占有CPU资源
同时把英雄的血量增加100倍,攻击减低到1,才有足够的时间观察到优先级的演示
如图可见,线程1的优先级是MAX_PRIORITY,所以它争取到了更多的CPU资源执行代码
Hero:
```
package charactor;
public class Hero {
public String name;
public float hp;
public int damage;
public void attackHero(Hero h) {
//把暂停时间去掉,多条线程各自会尽力去占有CPU资源
//线程的优先级效果才可以看得出来
/*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;
}
}
```
TestThread4:
```
package multiplethread;
import charactor.Hero;
public class TestThread4 {
public static void main(String[] args) {
Hero garen = new Hero();
garen.name = "盖伦";
garen.hp = 6160;
garen.damage = 1;
Hero teemo = new Hero();
teemo.name = "提莫";
teemo.hp = 3000;
teemo.damage = 1;
Hero bh = new Hero();
bh.name = "赏金猎人";
bh.hp = 5000;
bh.damage = 1;
Hero leesin = new Hero();
leesin.name = "盲僧";
leesin.hp = 5550;
leesin.damage = 1;
// 匿名类
Thread t1 = new Thread() {
public void run() {
while (!teemo.isDead()) {
garen.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();
}
}
```
# 临时暂停
当前线程,临时暂停,使得其他线程可以有更多的机会占用CPU资源
```
package multiplethread;
import charactor.Hero;
public class TestThread7 {
public static void main(String[] args) {
Hero garen = new Hero();
garen.name = "盖伦";
garen.hp = 6160;
garen.damage = 1;
Hero temmo = new Hero();
temmo.name = "提莫";
temmo.hp = 3000;
temmo.damage = 1;
Hero bh = new Hero();
bh.name = "赏金猎人";
bh.hp = 5000;
bh.damage = 1;
Hero lessin = new Hero();
lessin.name = "盲僧";
lessin.hp = 4550;
lessin.damage = 1;
Thread t1 = new Thread() {
@Override
public void run() {
while (!temmo.isDead()) {
garen.attackHero(temmo);
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
while (!lessin.isDead()) {
Thread.yield();
bh.attackHero(lessin);
}
}
};
t1.setPriority(5);
t2.setPriority(5);
t1.start();
t2.start();
}
}
```
# 守护线程
守护线程的概念是: 当一个进程里,所有的线程都是守护线程的时候,结束当前进程。
就好像一个公司有销售部,生产部这些和业务挂钩的部门。
除此之外,还有后勤,行政等这些支持部门。
如果一家公司销售部,生产部都解散了,那么只剩下后勤和行政,那么这家公司也可以解散了。
守护线程就相当于那些支持部门,如果一个进程只剩下守护线程,那么进程就会自动结束。
守护线程通常会被用来做日志,性能统计等工作。
```
package multiplethread;
public class TestThread5 {
public static void main(String[] args) {
Thread t = new Thread(){
@Override
public void run(){
int seconds = 0;
while (true) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.printf("已经玩了LOL %d 秒%n", seconds++);
}
}
};
t.setDaemon(true);
t.start();
}
}
```
# 练习-英雄充能
英雄有可以放一个技能叫做: 波动拳。
每隔一秒钟,可以发一次,但是只能连续发3次。
发完3次之后,需要充能5秒钟,充满,再继续发。
借助本章节学习到的知识点,实现这个效果
```
package charactor;
import java.io.Serializable;
public class Hero3 implements Serializable {
public String name;
public float hp;
public Hero3() {
}
public Hero3(String name) {
this.name = name;
}
public int damage;
public void attackHero(Hero h) {
try {
// 为了表示攻击需要时间,每次攻击暂停1000毫秒
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
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;
}
int totalTime = 3;
public void adugen() {
while (true) {
for (int i = 0; i < totalTime; i++) {
System.out.printf("波动拳第%d发%n", i + 1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("开始为时5秒的充能");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Hero3 h = new Hero3();
h.name = "红仔";
h.adugen();
}
}
```