5、线程状态
1.线程五大状态:
2.线程方法
2.1停止线程
案例
package com.xing.demo03; /** * 测试stop * 1.建议线程正常停止-->利用次数,不建议死循环 * 2.建议使用标志位-->设置一个标志位 * 3.不要使用stop或者destroy等过时或者JDK不建议使用的方法 */ public class TestStop implements Runnable { // 1. 设置一个标志位 private boolean flag = true; @Override public void run() { int i = 0; while (flag) { System.out.println("run...Thread" + i++); } } // 2. 设置一个公开的方法停止线程,转换标志位 public void stop() { this.flag = false; } public static void main(String[] args) { TestStop testStop = new TestStop(); new Thread(testStop).start(); for (int i = 0; i < 1000; i++) { System.out.println("main..." + i); if (i == 900) { //调用stop()切换标志位,让线程终止 testStop.stop(); System.out.println("该线程停止了"); } } } }
2.2线程休眠(阻塞)
案例
package com.xing.demo03; /** * 模拟网络延迟:放大问题的发生性 */ public class TestSleep implements Runnable { //票数 private int ticketNums = 10; @Override public void run() { while (true) { if (ticketNums <= 0) { break; } //捕获异常 try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "--->拿到了第" + ticketNums-- + "张票"); } } public static void main(String[] args) { TestSleep ticket = new TestSleep(); new Thread(ticket, "小红").start(); new Thread(ticket, "老师").start(); new Thread(ticket, "黄牛1").start(); } }
案例2
package com.xing.demo03; /** * 模拟倒计时 */ public class TestSleep2 { public static void main(String[] args) { try { tenDown(); } catch (InterruptedException e) { e.printStackTrace(); } } //模拟倒计时 public static void tenDown() throws InterruptedException { int num = 10; //10秒 while (true) { Thread.sleep(1000); //每一秒钟跑一次 System.out.println(num--); if (num <= 0) { break; } } } }
案例3
package com.xing.demo03; import java.text.SimpleDateFormat; import java.util.Date; /** * 每一秒获取当前时间 */ public class TestSleep3 { public static void main(String[] args) { //获取系统当前时间 Date startTime = new Date(System.currentTimeMillis()); while (true) { try { Thread.sleep(1000); System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime)); //更新系统时间 startTime = new Date(System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } } }
2.3线程礼让
案例
package com.xing.demo03; /** * 测试礼让线程 * 礼让不一定成功,看cpu心情 */ public class TestYield { public static void main(String[] args) { MyYeild myYeild = new MyYeild(); new Thread(myYeild, "a").start(); new Thread(myYeild, "b").start(); } } class MyYeild implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "线程开始执行"); Thread.yield();//礼让 System.out.println(Thread.currentThread().getName() + "线程停止执行"); } }
礼让成功,否则a线程执行完才执行b线程
礼让失败
2.4线程插队
案例
package com.xing.demo03; /** * 测试join * 插队 */ public class TestJoin implements Runnable { @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println("线程vip" + i); } } public static void main(String[] args) throws InterruptedException { //启动我们的线程 TestJoin testJoin = new TestJoin(); Thread thread = new Thread(testJoin); thread.start(); //主线程 for (int i = 0; i < 500; i++) { if (i == 200) { thread.join();//插队 } System.out.println("main" + i); } } }
3.线程状态观测
实现
package com.xing.demo03; /** * 观察测试线程状态 */ public class TestState { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); //这时是阻塞状态 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("//"); }); //观察状态 Thread.State state = thread.getState(); System.out.println(state); //观察启动后 thread.start();// 启动线程 state = thread.getState(); System.out.println(state);//Run while (state != Thread.State.TERMINATED) {//只要现成不终止,就一直输出状态 Thread.sleep(100); state = thread.getState();//更新线程状态 System.out.println(state); } //死亡后的线程不能再启动了,启动会报异常 //thread.start(); } }
4.线程优先级
-
Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。
-
线程的优先级用数字表示,范围从1~10.
-
Thread.MIN_PRIORITY = 1;
-
Thread.MAX_PRIORITY = 10;
-
Thread.NORM_PRIORITY = 5;
-
-
使用以下方式改变或获取优先级
-
getPriority()
-
setPriority(int xxx)
-
-
优先级的设定建议在start()调度前
-
优先级低只是意味着获得调度的概率低,并不是优先级低就不会被调用了,这都是看CPU的调度
数字越大优先级越高,但是优先级高的不一定先执行,只是先执行的概率大
实现
package com.xing.demo03; /** * 线程优先级 */ public class TestPriority{ public static void main(String[] args) { //主线程默认优先级 System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); MyPriority myPriority = new MyPriority(); Thread thread1 = new Thread(myPriority); Thread thread2 = new Thread(myPriority); Thread thread3 = new Thread(myPriority); Thread thread4 = new Thread(myPriority); Thread thread5 = new Thread(myPriority); //先设置优先级,再启动 thread1.start();//没有设置 //设置优先级 thread2.setPriority(1); thread2.start(); //设置优先级 thread3.setPriority(4); thread3.start(); //设置优先级 thread4.setPriority(Thread.MAX_PRIORITY);//MAX_PRIORITY=10 thread4.start(); //设置优先级 thread5.setPriority(8); thread5.start(); } } class MyPriority implements Runnable{ @Override public void run() { //打印线程优先级 System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); } }
5.守护(daemon)线程
-
线程分为用户线程和守护线程
-
虚拟机必须确保用户线程执行完毕
-
虚拟机不用等待守护线程执行完毕
-
守护线程如,后台记录操作日志,监控内存,垃圾回收等待..
实现
package com.xing.demo03; /** * 测试守护线程 * 上帝守护你 */ public class TestDaemon { //主线程 public static void main(String[] args) { God god = new God(); You you = new You(); Thread thread = new Thread(god); //默认false表示是用户线程,正常的线程都是用户线程... thread.setDaemon(true);//true 变为守护线程 //上帝守护线程启动 thread.start();//虚拟机不用等待守护线程执行完毕 //你 用户线程启动 new Thread(you).start();//虚拟机必须确保用户线程执行完毕 } } //上帝 class God implements Runnable{ @Override public void run() { while (true){ System.out.println("上帝保佑着你"); } } } //你 class You implements Runnable{ @Override public void run() { for (int i = 0; i < 36500; i++) { System.out.println("你一生都开心的活着"); } System.out.println("====goodbye!world===="); } }