Java线程的生命周期
先上图
从图中看到Java线程一共有6中状态
- new Thread(): 调用new关键字新建线程但是还没有调用start()方法称为创建状态
- 运行状态:Java线程中将就绪(ready)和运行中(running) 两种状态统称为“运行”
(1) ready: 线程对象创建后,其他线程调用了该对象的start()方法,此时线程开始运行并等待系统调用获取CPU的使用权,此时处于就绪状态
(2) running: 当就绪状态的线程获得CPU时间陪后变为运行中状态 - 阻塞(BLOCKED):线程没有获得锁被阻塞
- 等待(WAITING): 当线程在ready或者running状态时调用了sleep、wait、join、LockSupport.parkUntil等方法时线程进入等待状态;可通过notify、notifyall、LocaSupport.unpark等方法唤醒锁
- 超时等待(TIMED_WATING): 当线程在ready或者running状态时调用了sleep、wait、join、LockSupport.parkUntil等方法并设置了超时时间市线程进入等待状态呢,当等待时间超过设置的时间线程自动唤醒或者调用notify、notifyall、LocaSupport.unpark等方法唤醒锁
- 终止状态(TERMINATED):表示线程已经执行完毕
接下来我们用几个例子对线程的状态进行更加深刻的理解
案例一
//我们new一个线程并通过start去启动一个线程,
// 通过while(true)来保证线程不会中断,
// 最后通过TimeUnit.SECONDS.sleep并加上超时时间将线程阻塞后查看线程状态
new Thread(()->{
while (true){
try {
TimeUnit.SECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"Thread01").start();//阻塞状态
案例二
//我们new一个线程并通过start去启动一个线程,
// 通过while(true)来保证线程不会中断,
//通过synchronized去加锁
// 最后通过ThreadStatusDemo.class.wait()将线程阻塞后查看线程状态
new Thread(()->{
while (true) {
synchronized (ThreadStatusDemo.class) {
try {
ThreadStatusDemo.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"Thread02").start();//阻塞状态
案例三
static class BlockedDemo extends Thread{
@Override
public void run() {
synchronized (BlockedDemo.class){
while (true){
try {
TimeUnit.SECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
//创建一个静态的内部类继承Thread并覆盖run()方法
//synchronized加锁的目的是当两个线程去竞争锁时其中一个线程竞争到锁后另一个线程会进入阻塞状态,一直持续到拥有锁的线程释放锁
new Thread(new BlockedDemo(),"BLOCKED-DEMO-01").start();
new Thread(new BlockedDemo(),"BLOCKED-DEMO-02").start();
我在上边写了三个例子,现在通过jps和jstack命令去查看线程的状态
得到状态
案例一的状态
"Thread01" #11 prio=5 os_prio=0 tid=0x0000000018acb000 nid=0x26e8 waiting on condition [0x000000001948e000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
//在案例一中我们使用TimeUnit.SECONDS.sleep(100);将进程进行了阻塞,所以线程的状态变成了TIME_WAITING
案例二的状态
"Thread02" #12 prio=5 os_prio=0 tid=0x0000000018acd800 nid=0x3d4 in Object.wait() [0x000000001958f000]
java.lang.Thread.State: WAITING (on object monitor)
//在案例二中我们使用wait()将进程进行了阻塞,所以线程的状态变成了WAITING
案例三的状态
"BLOCKED-DEMO-01" #14 prio=5 os_prio=0 tid=0x0000000018ad0800 nid=0xdac waiting on condition [0x000000001968f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
"BLOCKED-DEMO-02" #16 prio=5 os_prio=0 tid=0x0000000018ad1000 nid=0x21a4 waiting for monitor entry [0x000000001978f000]
java.lang.Thread.State: BLOCKED (on object monitor)
//在案例中我们让两个线程去竞争锁
//01线程竞争到了锁,所以02线程直接进入阻塞状态(BLOCKED)
//01竞争到了锁所以01线程正常运行,但是我们又使用TimeUnit.SECONDS.sleep(100);方法将线程阻塞,所以线程的状态就是TIMED_WAITING了
BLOCKED 状态和WAITING 状态的区别
BLOCKED 是线程在竞争锁阻塞时的状态
WAITING 是使用sleep()/wait()/join()等方法将线程阻塞时使用的状态
TIMED_WAITING 是sleep()/wait()/join()等方法加了超时时间
扩展阅读
Java创建线程的三种方式