Java线程生命周期模型及各状态详解

Java线程生命周期模型

状态说明
NEW初始状态,构建完成的线程,并未调用start()方法,仅仅被new出来而已
RUNABLE运行状态,java线程中把准备就绪和正在运行的状态统一称为运行中,即RUNABLE,表示可以运行的状态
BLOCKED阻塞状态,此时线程被锁阻塞,并未执行
WAITING等待状态,表示线程进入等待状态,持续等待直到该线程所等待的线程执行完毕或中断,或是接收到通知运行的通知,即其他线程使用notify()或notifyAll()方法
TIMED_WAITING超时等待状态,没有耐心的线程,等待指定的时间后自行返回,停止等待
TERMINATED终止状态,表示线程已执行完毕

各生命周期的转化方法

从无到NEW(实例化)Thread thread = new Thread(yourThread);
NEW->RUNABLEThread.start()
RUNABLE->BLOCKED等待进入synchronized方法/块
BLOCKED->RUNABLE获取到该synchronized方法/块的锁
RUNABLE->WAITINGObject.wait(),Thread.jion(),LockSupport.park()
RUNABLE->TIMED_WAITINGObject.wait(long),Thread.jion(long),Thread.sleep(long),LockSupport.parkNanos(),LockSupport.parkUntil()
WAITING/TIMED_WAITING->RUNABLEObject.notify(),Object.notifyAll(),LockSupport.unpark(Thread)
RUNABLE->TERMINATED执行完毕即终止运行

各生命周期详解

NEW - 创建线程

运行线程前首先要构造一个线程对象出来,创建线程一般有三种方式

1.继承Thread类并重写run方法

public class MyThread extends Thread{
    @override
    void run(){
        //......
    }
}

2.实现Runable接口

public class MyThread implements Runnable{
    public void run(){
        //......
    }
}

3.实现Callable和Future接口

public class MyThread implements Callable{
    public Object call(){
        //remember return something
        return "whatever you want";
    }
}

三种方法的优劣

方法优势劣势
继承Thread类并重写run方法编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。已经继承了Thread作为父类,不能继承其他父类
实现Runable,Callable和Future接口线程只是实现了接口,还可以继承其他类,避免了Java不能多重继承的限制编程复杂度较高,如果要访问当前线程,则必须使用Thread.currentThread()方法。

构造完线程对象后,此时还并未调用start()方法,可以在此时对线程进行设置,诸如:

优先级,父线程,是否为后台线程,所属线程组,线程池等。

RUNABLE - 运行线程

对已经实例化的Thread对象调用start()方法,即可让其进入RUNABLE状态。start()的具体语义是:当前线程同步告知jvm,只要线程规划器空闲,应立即启动调用start()的线程。

BLOCKED - 线程阻塞

java线程的阻塞与I/O的阻塞是不同的,BLOCKED(阻塞状态)特指进入同步方法、块时的阻塞。

更加详细的定义可以参考 Thread.State 中的 javadoc:

/**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */

此处翻译来源:Java 线程状态之 BLOCKED

这句话很长,可以拆成两个简单句来理解。

  1. A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method。

    一个处于 blocked 状态的线程正在等待一个监视器锁以进入一个同步的块或方法。

  2. A thread in the blocked state is waiting for a monitor lock to reenter a synchronized block/method after calling Object.wait。

    一个处于 blocked 状态的线程正在等待一个监视器锁,在其调用 Object.wait 方法之后,以再次进入一个同步的块或方法。

通过上述翻译,我们可以知道,阻塞将会发生在:

1.当前线程进入同步方法、块时,等待锁的获取

2.重新进入当前同步块时,等待锁的获取

其中详细解释一下2。如果同步方法、块中,调用了Object.wait方法,则当前线程会释放所占用的锁,在其wait结束后,则需要重新获取该同步方法、块的锁,所以在获取不到锁时,将会使该线程阻塞。

WAITING及TIMED_WAITING - 等待状态

要进入WAITING或TIMED_WAITING的状态,需要该线程在RUNABLE时调用Object.wait,Thread.join,LockSupport.park等方法。对于WAITING及TIMED_WAITING状态,WAITING状态详细的语义为,该线程目前在等待进一步指示,主动进行暂停。

想要通知WAITING及TIMED_WAITING状态的线程返回RUNABLE,则需要使用**Object.notify(),Object.notifyAll(),LockSupport.unpark(Thread)**等方法。

值得注意的是,wait()方法会使当前线程释放所持有的锁。所以上文提到的WAITING状态结束,被使用上述函数唤醒后,如果要运行或运行在同步方法、块,则需要重新参与锁的竞争,故线程有可能从WAITING及TIMED_WAITING状态在进入RUNABLE状态后瞬间被堵塞变为BLOCKED状态,即使线程是从同步方法、块中被唤醒,也会被堵塞。

TERMINATED - 终止状态

当线程运行完毕,则进入终止状态,如果线程在阻塞时被使用Thread.interrupt()中断,也会进入终止状态。要注意,原本用于终止线程的stop()方法已经过时,原因是这个方法会导致所占用资源的释放出现异常,可能会产生死锁现象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值