多线程10:线程状态及常见方法
线程状态:
- new一个Thread对象时候就处于新生状态了。
- 调用start方法,立即进入就绪状态。等待cpu的调度
- cpu调度时,进入运行状态。cpu调度谁看心情
- 运行时,调用sleep(),wait()或同步锁定时,线程进入阻塞状态,阻塞解除后进入就绪状态
- 如果正常执行完毕进入死亡状态。
线程方法:
1.停止线程:
- 不推荐使用JDK使用的stop()、destroy()方法。
[已废弃]@Deprecated,Ctrl+左键打开Thread类-->Structrue-->找到
对应方法就能看见以下代码:
1 @Deprecated 2 public void destroy() { 3 throw new NoSuchMethodError(); 4 } 5 6 @Deprecated 7 public final void stop() { 8 SecurityManager security = System.getSecurityManager(); 9 if (security != null) { 10 checkAccess(); 11 if (this != Thread.currentThread()) { 12 security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION); 13 } 14 } 15 // A zero status value corresponds to "NEW", it can't change to 16 // not-NEW because we hold the lock. 17 if (threadStatus != 0) { 18 resume(); // Wake up thread if it was suspended; no-op otherwise 19 } 20 21 // The VM can handle all thread states 22 stop0(new ThreadDeath()); 23 }
- 推荐线程自己停止下来
- 建议使用一个标志位进行终止变量当flag=false,则终止线程运行。
思路:
通过一个flag,设立一个外部标志位,然后通过一个公开的方法,我们去调用这个方法,来切换一下标志位,让线程停止
1 package com.thread.state; 2 3 //测试stop 4 //1.建议线程正常停止--->利用次数,不建议死循环 5 //2.建议使用标志位--->设置一个标志位 6 //3.不要使用stop和的、destroy等过时或者JDK不建议使用的方法 7 8 public class TestStop implements Runnable { 9 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 23 public void stop() { 24 this.flag = false; 25 } 26 27 public static void main(String[] args) { 28 TestStop testStop = new TestStop(); 29 new Thread(testStop).start(); 30 31 for (int i = 0; i < 1000; i++) { 32 System.out.println("main" + i); 33 if (i == 900) { 34 //调用自己写的stop方法切换标志位,让线程停止 35 testStop.stop(); 36 System.out.println("线程该停止了"); 37 } 38 } 39 40 } 41 42 }
2.线程休眠:
- sleep(时间)指定当前线程阻塞的毫秒数
- sleep存在异常InterrruptedException
- sleep时间达到后线程进入就绪状态
- sleep可以模拟网络延时,倒计时等
- 每一个对象都有一个锁,sleep不会释放锁
案例一:模拟网络延时:放大问题的发生性
1 package com.thread.state; 2 3 //模拟网络延时:放大问题的发生性 4 public class TestSleep implements Runnable { 5 6 //票数 7 private int ticketNums = 10; 8 9 @Override 10 public void run() { 11 while (true) { 12 if (ticketNums <= 0) { 13 break; 14 } 15 //模拟延时 16 try { 17 Thread.sleep(100); 18 } catch (InterruptedException e) { 19 e.printStackTrace(); 20 } 21 22 System.out.println(Thread.currentThread().getName() + "-->拿到了" + ticketNums-- + "票"); 23 } 24 } 25 26 public static void main(String[] args) { 27 28 TestSleep ticket = new TestSleep(); 29 30 new Thread(ticket, "小红").start(); 31 new Thread(ticket, "老师").start(); 32 new Thread(ticket, "黄牛").start(); 33 } 34 35 }
案例二:模拟倒计时
1 package com.thread.state; 2 3 //模拟倒计时 4 public class TestSleep2 { 5 6 public static void main(String[] args) { 7 try { 8 tenDown(); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 13 } 14 15 //模拟倒计时 16 public static void tenDown() throws InterruptedException { 17 int num = 10; 18 19 while (true) { 20 Thread.sleep(1000); 21 System.out.println(num--); 22 if (num <= 0) { 23 break; 24 } 25 } 26 } 27 }
案例三:打印系统当前时间
1 package com.thread.status; 2 3 import java.text.SimpleDateFormat; 4 import java.util.Date; 5 6 //模拟倒计时 7 public class TestSleep2 { 8 9 public static void main(String[] args) { 10 //打印当前系统时间 11 Date startTime = new Date(System.currentTimeMillis());//获取系统当前时间 12 13 while (true) { 14 try { 15 Thread.sleep(1000); 16 System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime)); 17 startTime = new Date(System.currentTimeMillis());//更新当前时间 18 } catch (InterruptedException e) { 19 e.printStackTrace(); 20 } 21 } 22 } 23 } 24 结果: 25 17:28:27 26 17:28:28 27 17:28:29 28 17:28:30 29 17:28:31 30 ...
3.线程礼让:
- 礼让线程,让当前正在执行的线程暂停,但不阻塞
- 将线程从运行状态转为就绪状态
- 让cpu重新调度,礼让不一定成功!看cpu心情
1 package com.thread.state; 2 3 //测试礼让线程 4 //礼让不一定成功,看cpu心情 5 public class TestYield { 6 7 public static void main(String[] args) { 8 MyYield myYield = new MyYield(); 9 10 new Thread(myYield, "a").start(); 11 new Thread(myYield, "b").start(); 12 13 } 14 } 15 16 class MyYield implements Runnable { 17 18 @Override 19 public void run() { 20 System.out.println(Thread.currentThread().getName() + "线程开始执行"); 21 Thread.yield();//礼让 22 System.out.println(Thread.currentThread().getName() + "线程停止执行"); 23 } 24 } 25 26 结果: 27 b线程开始执行 28 a线程开始执行 29 b线程停止执行 30 a线程停止执行 礼让成功 31 32 a线程开始执行 33 a线程停止执行 34 b线程开始执行 35 b线程停止执行 礼让失败,线程正常结束
4.Join合并线程:
- Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞
- 可以想象成插队
1 package com.thread.state; 2 3 //测试Join方法-->想象为插队 4 public class TestJoin implements Runnable { 5 6 @Override 7 public void run() { 8 for (int i = 0; i < 1000; i++) { 9 System.out.println("线程vip来了" + i); 10 } 11 } 12 13 public static void main(String[] args) throws InterruptedException { 14 15 //启动我们的线程 16 TestJoin testJoin = new TestJoin(); 17 Thread thread = new Thread(testJoin); 18 thread.start(); 19 20 21 //主线程 22 for (int i = 0; i < 500; i++) { 23 if (i == 200) { 24 thread.join();//插队 25 } 26 System.out.println("main" + i); 27 } 28 29 } 30 }
5.线程状态观测:查看JDK帮助文档
public static enum Thread.State extends Eunm<Thread.State>
线程状态。线程可以处于以下状态之一
- NEW
- 尚未启动的线程处于此状态。
- RUNNABLE
- 在Java虚拟机中运行的线程处于此状态。
- BLOCKED
- 被阻塞等待监视器锁定的线程处于此状态。
- WAITING
- 正在等待另一个线程执行特定动作的线程。
- TIMED_WAITING
- 正在等待另一个线程执行动作达到指定等待时间的线程。
- TERMINATED
- 已退出的线程处于此状态。
一个线程可以在给定时间点处于一个状态。这些状态是不反映任何操作系统线程状态的虚拟机状态。
1 package com.thread.state; 2 3 //观察测试线程状态 4 public class TestState { 5 6 public static void main(String[] args) throws InterruptedException { 7 Thread thread = new Thread(() -> { 8 for (int i = 0; i < 5; i++) { 9 try { 10 Thread.sleep(1000); 11 } catch (InterruptedException e) { 12 e.printStackTrace(); 13 } 14 } 15 System.out.println("///////"); 16 }); 17 18 19 //观察状态 20 Thread.State state = thread.getState(); 21 System.out.println(state);//NEW 22 23 //观察启动后 24 thread.start();//启动线程 25 state = thread.getState(); 26 System.out.println(state);//RUNNABLE 27 28 while (state != Thread.State.TERMINATED) {//只要线程不终止,就一直输出状态 29 Thread.sleep(100); 30 state = thread.getState();//更新线程状态 31 System.out.println(state);//输出状态 32 } 33 } 34 } 35 36 结果: 37 NEW 38 RUNNABLE 39 TIMED_WAITING 40 TIMED_WAITING 41 TIMED_WAITING 42 TIMED_WAITING 43 TIMED_WAITING 44 TIMED_WAITING 45 TIMED_WAITING 46 TIMED_WAITING 47 TIMED_WAITING 48 TIMED_WAITING 49 TIMED_WAITING 50 TIMED_WAITING 51 TIMED_WAITING 52 TIMED_WAITING 53 TIMED_WAITING 54 TIMED_WAITING 55 TIMED_WAITING 56 TIMED_WAITING 57 TIMED_WAITING 58 TIMED_WAITING 59 TIMED_WAITING 60 TIMED_WAITING 61 TIMED_WAITING 62 TIMED_WAITING 63 TIMED_WAITING 64 TIMED_WAITING 65 TIMED_WAITING 66 TIMED_WAITING 67 TIMED_WAITING 68 TIMED_WAITING 69 TIMED_WAITING 70 TIMED_WAITING 71 TIMED_WAITING 72 TIMED_WAITING 73 TIMED_WAITING 74 TIMED_WAITING 75 TIMED_WAITING 76 TIMED_WAITING 77 TIMED_WAITING 78 TIMED_WAITING 79 TIMED_WAITING 80 TIMED_WAITING 81 TIMED_WAITING 82 TIMED_WAITING 83 TIMED_WAITING 84 /////// 85 TERMINATED 86 87 Process finished with exit code 0 88 新生进入NEW状态, start启动后进入RUNNABLE状态,休眠1秒进入WAITING状态每隔100ms 89 更新一次状态,最后结束后输出一句话//////,最终进入TERMINATED状态
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步