【Java EE】多线程-初阶-线程的状态
多线程-初阶-线程的状态
- 线程的状态
- 3.1 观察线程的所有状态
- 3.2 线程状态和状态转移的意义
- 3.3 观察线程的状态和转移
线程的状态
就绪: 这个线程随时可以去 cpu 上执行.(也包含正在 cpu 上执行)
阻塞: 这个线程暂时不方便去 cpu 上执行.Java 中,针对阻塞状态又做了进一步的细分
3.1 观察线程的所有状态
线程的状态是⼀个枚举类型 Thread.State
public class ThreadState {public static void main(String[] args) {for (Thread.State state : Thread.State.values()) {System.out.println(state);}}
}
Java 中,线程有以下几种状态:
• NEW: 安排了⼯作, 还未开始⾏动
• RUNNABLE: 可⼯作的. ⼜可以分成正在⼯作中和即将开始⼯作.
• BLOCKED: 这⼏个都表⽰排队等着其他事情
• WAITING: 这⼏个都表⽰排队等着其他事情
• TIMED_WAITING: 这⼏个都表⽰排队等着其他事情
• TERMINATED: ⼯作完成了.
- NEW Thread 对象创建好了,但是还没有调用 start 方法在系统中创建线程
- TERMINATED Thread 对象仍然存在,但是系统内部的线程已经执行完毕了
- RUNNABLE 就绪状态,表示这个线程正在 cpu 上执行,或者准备就绪随时可以去 cpu 上执行
- TIMED WAITING 指定时间的阻塞, 就在到达一定时间之后自动解除阻塞。使用 sleep 会进入这个状态. 使用带有超时时间的join也会
- WAITING 不带时间的阻塞 (死等),必须要满足一定的条件,才会解除阻塞。join 或者 wait 都会进入 WAITING
- BLOCKED 由于锁竞争,引起的阻塞.(后面线程安全的时候具体介绍)
3.2 线程状态和状态转移的意义
⼤家不要被这个状态转移图吓到,我们重点是要理解状态的意义以及各个状态的具体意思。
还是我们之前的例⼦:
刚把李四、王五找来,还是给他们在安排任务,没让他们⾏动起来,就是 NEW 状态;
当李四、王五开始去窗⼝排队,等待服务,就进⼊到 RUNNABLE 状态。该状态并不表⽰已经被银⾏⼯作⼈员开始接待,排在队伍中也是属于该状态,即可被服务的状态,是否开始服务,则看调度器的调度;
当李四、王五因为⼀些事情需要去忙,例如需要填写信息、回家取证件、发呆⼀会等等时,进⼊BLOCKED 、 WATING 、 TIMED_WAITING 状态,⾄于这些状态的细分,我们以后再详解;
如果李四、王五已经忙完,为 TERMINATED 状态。
所以,之前我们学过的 isAlive() ⽅法,可以认为是处于不是 NEW 和TERMINATED 的状态都是活着的。
学习这些状态,最大的作用,调试多线程代码的 bug 的时候,给我们作为重要的参考依据。"程序卡住了"意味着一些关键的线程阻塞了,就可以观察线程的状态,就能分析出一些原因。
如果发现某个进程"卡住了,就可以使用 jconsole 这样的工具,查看这个进程中的一些重要线程的状态和调用栈。通过状态,就可以判定线程是否是阻塞,以及什么原因阻塞的~
一个 Thread 对象只能 start 一次,和线程状态密切相关的. 只有处于 NEW状态才能 start。WAITING 和 BLOCKED 后面再介绍
3.3 观察线程的状态和转移
观察 1: 关注 NEW 、 RUNNABLE 、 TERMINATED 状态的转换
public class ThreadStateTransfer {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {for (int i = 0; i < 1000_0000; i++) {}}, "李四");System.out.println(t.getName() + ": " + t.getState());;t.start();while (t.isAlive()) {System.out.println(t.getName() + ": " + t.getState());;}System.out.println(t.getName() + ": " + t.getState());;}
}
观察 2: 关注 WAITING 、 BLOCKED 、 TIMED_WAITING 状态的转换
public static void main(String[] args) {final Object object = new Object();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {synchronized (object) {while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}}, "t1");t1.start();Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {synchronized (object) {System.out.println("hehe");}}}, "t2");t2.start();
}
使⽤ jconsole 可以看到 t1 的状态是 TIMED_WAITING , t2 的状态是BLOCKED
修改上⾯的代码, 把 t1 中的 sleep 换成 wait
public static void main(String[] args) {final Object object = new Object();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {synchronized (object) {try {// [修改这⾥就可以了!!!!!]// Thread.sleep(1000);object.wait();} catch (InterruptedException e) {e.printStackTrace();}}}}, "t1");...
}
使⽤ jconsole 可以看到 t1 的状态是 WAITING
结论:
• BLOCKED 表⽰等待获取锁, WAITING 和 TIMED_WAITING 表⽰等待其他线程发来通知.
• TIMED_WAITING 线程在等待唤醒,但设置了时限; WAITING 线程在⽆限等待唤醒