线程的生命周期
# 前言
前面我们学习了线程的创建和使用,接下来学习它的生命周期。
所谓生命周期,就是它的创建到毁灭的周期。
# Thread.State
在Java中,JDK中用Thread.State
类定义了线程的几种状态,代表它的声明周期。
State
类是Thread
类的内部枚举类。我们可以来看看它的源码:
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
/**
* 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}.
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
- 1、
NEW
:线程对象被新建,但是未启动 - 2、
RUNNABLE
:线程运行起来 - 3、
BLOCKED
:线程阻塞 - 4、
WAITING
:线程等待状态 - 5、
TIMED_WAITING
:具有指定等待时间的等待线程的线程状态 - 6、
TERMINATED
:消亡
在Java中,它是通过方法来定义它的状态,其实它的状态我们可以重新定义,以至于让我们更加快能理解它的状态。
要想实现多线程,必须在主线程中创建新的线程对象。Java语言使用Thread
类及其子类的对象来表示线程,在它的一个完整的生命周期中通常要经历如下的五种状态:
- 1、新建:当一个
Thread
类或其子类的对象被声明并创建时,新生的线程对象处于新建状态 - 2、就绪:处于新建状态的线程被
start()
后,将进入线程队列等待CPU
时间片,此时它已具备了运行的条件,只是没分配到CPU
资源 - 3、运行:当就绪的线程被调度并获得
CPU
资源时,便进入运行状态,run()
方法定义了线程的操作和功能 - 4、阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出
CPU
并临时中止自己的执行,进入阻塞状态 - 5、死亡:线程完成了它的全部工作或线程被提前强制性地中止或出现异常导致结束
# 线程状态转换图
说明:
- 1、生命周期关注两个概念:状态、相应的方法
- 2、关注一个状态到另一个状态,执行了哪个回调方法
- 3、关注调用方法,导致状态变化
- 4、阻塞:临时状态
- 5、死亡:最终状态
# 就绪
注意:线程调用了
start()
方法它不会立刻运行,而是进入就绪状态,等待CPU分配资源获取执行权,才会去运行。
像之前的案例调用线程的时候,它的执行顺序并不是从上到下执行的,而是等待CPU分配资源获取执行权:
class Window2 implements Runnable {
private int ticket = 100;
public void run() {
while (true) {
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
ticket--;
} else {
// System.out.println(Thread.currentThread().getName() + "抢不到票,卖光了!");
break;
}
}
}
}
public class WindowTest2 {
public static void main(String[] args) {
Window2 w1 = new Window2();
Thread t1 = new Thread(w1);
Thread t2 = new Thread(w1);
Thread t3 = new Thread(w1);java
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 阻塞
阻塞不是线程的最终状态,线程的最终状态只能是死亡。
如果程序一直是阻塞状态,那么这个程序很大问题。
等待同步锁
是指为了解决多线程并发时的安全问题,都想去操作数据,只让一个线程去操作,其他线程要等待获取同步锁,才结束阻塞状态。
join
当别的线程A调用了join状态,那么B线程就进入阻塞状态,当A执行完了,B才会结束阻塞状态。
sleep
当线程调用sleep
方法,那么线程就进入阻塞状态,当时间到了,自动回到就绪状态。
suspend()
:线程挂起,已经被弃用
- This method has been deprecated, as it is inherently deadlock-prone. If the target thread holds a lock on the monitor protecting a critical system resource when it is suspended, no thread can access this resource until the target thread is resumed. If the thread that would resume the target thread attempts to lock this monitor prior to calling
resume
, deadlock results. Such deadlocks typically manifest themselves as "frozen" processes. For more information, see Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?.
为什么被弃用?因为它可能会导致死锁,什么是死锁一会后面说。
resume()
:线程结束结束挂起状态
- This method exists solely for use with
suspend()
, which has been deprecated because it is deadlock-prone. For more information, see Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?.
这个方法一般搭配suspend()
一起使用,它们是一对出现的。
# 死亡
Errror
或Exception
且未处理
stop()
:调用线程的stop()
方法
线程还没运行完就被强制消亡。
帮我改善此页面 (opens new window)
上次更新: 2020/12/23, 03:15:32