Java多线程学习七 线程组

一、线程状态

1. 初始(NEW)

新创建了一个线程对象,但还没有调用start()方法。

2. 运行(RUNNABLE)

Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。

3. 阻塞(BLOCKED)

表示线程阻塞于锁。
BLOCKED称为阻塞状态,或者说线程已经被挂起,它“睡着”了,原因通常是它在等待一个“锁”,当尝试进入一个synchronized语句块/方法时,锁已经被其它线程占有,就会被阻塞,直到另一个线程走完临界区或发生了相应锁对象的wait()操作后,它才有机会去争夺进入临界区的权利
在Java代码中,需要考虑synchronized的粒度问题,否则一个线程长时间占用锁,其它争抢锁的线程会一直阻塞,直到拥有锁的线程释放锁
处于BLOCKED状态的线程,即使对其调用 thread.interrupt()也无法改变其阻塞状态,因为interrupt()方法只是设置线程的中断状态,即做一个标记,不能唤醒处于阻塞状态的线程
注意:ReentrantLock.lock()操作后进入的是WAITING状态,其内部调用的是LockSupport.park()方法

4. 等待(WAITING):

进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
处于这种状态的线程不会被分配CPU执行时间,它们要等待显示的被其它线程唤醒。这种状态通常是指一个线程拥有对象锁后进入到相应的代码区域后,调用相应的“锁对象”的wait()方法操作后产生的一种结果。变相的实现还有LockSupport.park()、Thread.join()等,它们也是在等待另一个事件的发生,也就是描述了等待的意思。
以下方法会让线程陷入无限期等待状态:
(1)没有设置timeout参数的Object.wait()
(2)没有设置timeout参数的Thread.join()
(3)LockSupport.park()

注意:
LockSupport.park(Object blocker) 会挂起当前线程,参数blocker是用于设置当前线程的“volatile Object parkBlocker 成员变量”
parkBlocker 是用于记录线程是被谁阻塞的,可以通过LockSupport.getBlocker()获取到阻塞的对象,用于监控和分析线程用的。

“阻塞”与“等待”的区别:
(1)“阻塞”状态是等待着获取到一个排他锁,进入“阻塞”状态都是被动的,离开“阻塞”状态是因为其它线程释放了锁,不阻塞了;
(2)“等待”状态是在等待一段时间 或者 唤醒动作的发生,进入“等待”状态是主动的
如主动调用Object.wait(),如无法获取到ReentraantLock,主动调用LockSupport.park(),如主线程主动调用 subThread.join(),让主线程等待子线程执行完毕再执行
离开“等待”状态是因为其它线程发生了唤醒动作或者到达了等待时间

5. 超时等待(TIMED_WAITING)

该状态不同于WAITING,它可以在指定的时间后自行返回。
处于这种状态的线程也不会被分配CPU执行时间,不过无需等待被其它线程显示的唤醒,在一定时间之后它们会由系统自动的唤醒。

以下方法会让线程进入TIMED_WAITING限期等待状态:
(1)Thread.sleep()方法
(2)设置了timeout参数的Object.wait()方法
(3)设置了timeout参数的Thread.join()方法
(4)LockSupport.parkNanos()方法
(5)LockSupport.parkUntil()方法

6. 终止(TERMINATED)

表示该线程已经执行完毕。

二、线程组

你可能感兴趣的:(Java多线程学习七 线程组)