🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[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(); } } ```