【多线程】- Java中线程以及线程池的状态

mac2025-07-11  2

一、线程的5种状态

新建(New) :使用new Thread() 创建一个线程之后。

运行(Runnable) :使用Thread.start() 方法之后。启动一个线程,该线程会进入等待队列等待CPU的执行,因此可以细分为runnable和running状态。

无限等待(waiting) :处于这种状态的线程,不会被分配CPU执行时间,需要等待其他线程显式地唤醒,然后进入运行状态。

调用Thread.join() 方法。将会一直等待上一个线程的执行结束,然后被上一个线程唤醒。调用Object.wait() 方法。将会一直等待,直到其他线程中使用了notify()、notifyAll()进行唤醒。调用LockSupport.park()方法。

有限等待(timed waiting) :处于这种状态的线程,不会被分配CPU执行时间,既可以被其他线程显式地唤醒,也可以在一定时间后由系统自动唤醒,然后进入运行状态。

调用Thread.sleep(timeout) 方法。该方法不会释放持有的对象锁。调用Object.wait(timeout) 方法。该方法会释放持有的锁。调用Thread.join(timeout) 方法。调用LockSupport.parkNanos()或者LockSupport.parkUntil()方法。

阻塞(blocked) :阻塞和等待的区别在于,阻塞是在等待获取一个排它锁,因为该线程获取不到锁所以被阻塞住而不能允许;而等待则是等待一段时间或者是等待被唤醒,等待状态并不是等待获取锁。这个状态有个特点,一个线程请求锁,得到之后该线程进入阻塞状态;而其他线程再来请求锁,由于得不到而阻塞;当该锁释放后,被阻塞的线程得到锁就进入了运行状态。

由synchronized 修饰的代码块、方法。使得线程之间有并行变成串行执行。IO操作,也是串行执行。

结束(terminated) :当线程的run() 方法执行结束后,该线程就结束了。

其状态转换图如下:

二 线程池状态

RUNNING :线程池的初始化状态是RUNNING,线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理。

SHOTDOWN : 处于该状态的线程池不会接受新任务,但是仍会继续处理已有任务。

处于RUNNING状态的线程池调用showDown()方法后进入该状态。

STOP : 处于该状态的线程池不会接受新任务,同时不会继续处理已有任务,会中断正在处理的任务。

处于RUNNINGor SHUTDOWN状态的线程池调用showDownNow()方法进入该状态。

TIDDING : 当所有的任务已终止,当线程池中任务数量为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。

当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。 当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。

TERMINATED : 线程池彻底终止,就变成TERMINATED状态。

线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。

状态转换图如下:

小tips:线程池中线程的状态

若为核心线程 且 allowCoreThreadTimeOut 为false: 那核心线程在执行任务完后,会处于阻塞blocking状态,直到下一个任务取出它若为核心线程 且 allowCoreThreadTimeOut 为true: 核心线程如果在keepAliveTime时间内没有新的任务,超时时间之前,处于阻塞状态blocking,超时时间到了后,线程状态将变为dead(terminated)若为非核心线程: 超时时间(keepAliveTime)之前阻塞状态blocking,超时时间之后,dead(terminated)如果线程池关闭了,那所有的线程都会变为dead(terminated)
最新回复(0)