线程的状态
线程的状态总共分有:初始态、运行态、等待态、超时等待态、阻塞态、终止态。
初始态
由Thread创建对象,还没有使用start启动线程,称为初始态。
就绪状态
在JAVA中的就绪状态分为:就绪状态和运行状态。
就绪状态:指线程获得运行的所有资源,只需要等待CPU分配执行权就可以立即运行。有一个就绪队列存储就绪状态的线程。
运行状态:指已经获得cpu执行权正在执行的线程。CPU在每个时间段只能执行一个线程,所以在每个CPU时间段只有一个就绪状态的线程。
阻塞状态
- 由于正在运行的线程请求某一个资源失败,进入阻塞状态。
- 所有请求锁失败的线程也是进入阻塞状态。
- 阻塞队列中存储所有阻塞状态的线程。
- 阻塞状态的线程会不断的请求资源,一旦请求成功就会立即进入就绪状态,等待执行。
等待状态
- 正在运行的线程调用Object.wait(),Thread.join(),LockSupport.part()就会进入等待状态。
- 等待状态的线程需要等待其他线程的信号才能继续运行。
- 等待队列存储所有的等待状态的线程。
- 进入等待就是立即释放CPU执行权,和占有资源。
超时等待状态
- 正在运行的线程调用Thread.sleep,Object.wait,Thread.join,LockSupport.partNanos,LockSupport.partUntil。就会进入该状态。
- 他和等待状态一样,并不是因为请求不到资源而进入,而是主动进入。他运行时需要其他线程唤醒。
- 进入该状态会释放CPU执行权和占有资源。
- 超时后会自动进入超时队列。
初始状态->就绪状态
线程调用start进入就绪状态,如果前面已经没有就绪线程,那么就会进入运行状态。
就绪状态->运行状态
系统调用。
运行状态->就绪状态
①:调用Thread.yield;②系统调用。
运行态->阻塞状态
请求锁/资源失败时。
阻塞状态->运行态
阻塞队列中的线程会不断检查锁是否可用,一旦可用就进入就绪队列。
运行态->等待状态
- 调用Object.wait方法
- 调用Thread.join方法
- 调用LockSupport.part()方法
等待状态->阻塞状态
锁对象.notify(),方法并且等待线程需要锁同步。
状态重点
- wait会释放cpu执行权和占用的锁。
- sleep只释放CPU执行权,不释放占用锁;线程被放入超时等待队列,和yield相比,他使线程较长时间不能运行。
- yield方法只释CPU执行权,锁依然被占用,线程放入就绪队列,短时间能被运行。
- wait和notify必须配套使用,即必须使用同一把锁调用。
- wait和notify必须放在同一个同步块中。
- 调用wait和notify的对象必须是他们所处同步块的锁对象。
中断
- 中断只是一种协作机制,java并没有对其增加任何语法,中断过程完全需要程序员自己实现。若现在需要中断一个线程,需要手动的调用该线程的interputed方法,该方法也只是将线程对象的中断标识设置为true;然而程序员需要不断的判断标识位的值。
- 每个线程都有一个标识位,用于表示线程是否被中断。
- 通过调用线程方法interputed方法
中断重要的方法
- public void interrupt(),将调用者线程的状态设置为true。
- public boolearn isInterrupted();判断调用者的中断状态。
- public static boolearn interrupted()调用。返回当前线程的中断状态;将当前的中断状态设置为false。
- resume 恢复调用者线程,让他处于就绪状态。
- stop和suspend两个方法已经失效,原因是使用后会出现很多不可控。
使用样例
1 volatile static boolean isterrupt=false; 2 public static void main(String[] args) { 3 4 Thread t1=new Thread(new Runnable() { 5 public void run() { 6 while(!isterrupt) { 7 //正常任务代码 8 System.out.println("continue"); 9 } 10 System.out.println("bai"); 11 //中断处理的代码 12 13 } 14 }); 15 t1.start(); 16 Thread t2=new Thread(new Runnable() { 17 18 @Override 19 public void run() { 20 isterrupt=true; 21 22 } 23 }); 24 25 t2.start(); 26 27 }
方式二
1 public static void main(String[] args) { 2 3 Thread t1=new Thread(new Runnable() { 4 public void run() { 5 while(!Thread.currentThread().isInterrupted()) { 6 //正常任务代码 7 System.out.println("continue"); 8 } 9 System.out.println("bai"); 10 //中断处理的代码 11 12 } 13 }); 14 t1.start(); 15 Thread t2=new Thread(new Runnable() { 16 17 @Override 18 public void run() { 19 t1.interrupt(); 20 21 } 22 }); 23 t2.start(); 24 25 }