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