目次
-
- 1. 5 つの州
- 2. 6 つの州
-
- Thread.State 列挙によると、6 つの状態に分けられます。
- Java で状態を確認する
- さまざまな状況での Java の 6 つの状態の遷移を分析してみましょう
-
-
- ケース 1 `NEW --> RUNNABLE`
- ケース 2 `RUNNABLE <--> WAITING`
- ケース 3 `RUNNABLE <--> WAITING`
- ケース 4 `RUNNABLE <--> WAITING`
- ケース 5 `RUNNABLE <--> TIMED_WAITING`
- ケース 6 `RUNNABLE <--> TIMED_WAITING`
- ケース 7 `RUNNABLE <--> TIMED_WAITING`
- ケース 8 `RUNNABLE <--> TIMED_WAITING`
- ケース 9 `RUNNABLE <--> BLOCKED`
- ケース 10 `RUNNABLE <--> TERMINATED`
-
1. 5 つの州
これは、オペレーティング システム レベルから記述されます。
- [作成ステータス] スレッド オブジェクトは言語レベルでのみ作成され、オペレーティング システムのスレッドにはまだ関連付けられていません
- [実行可能状態] (準備完了状態) は、スレッドが作成され (オペレーティング システム スレッドに関連付けられ)、CPU によってスケジュールおよび実行できることを意味します。
- [稼働状況]とは、CPUタイムスライスの稼働状況を取得している状態を指します。
- CPU タイム スライスが使い果たされると、[実行中状態] から [実行可能状態] に切り替わり、スレッド コンテキストの切り替えが発生します。
- 【ブロッキング状態】
- BIO のファイルの読み書きなど、ブロッキング API が呼び出されると、スレッドはこの時点で実際には CPU を使用しないため、スレッド コンテキストが切り替わり、[ブロック状態] に入ります。
- BIO 操作が完了すると、オペレーティング システムはブロックされたスレッドを起動し、[実行可能な状態] に切り替えます。
- [実行可能な状態] との違いは、[ブロックされた状態] のスレッドの場合、それらがウェイクアップしない限り、スケジューラーはそれらのスケジューリングを考慮しないことです。
- 【終了状態】 スレッドが実行され、ライフサイクルが終了し、他の状態に遷移しないことを示します
状態遷移条件:
- Ready 状態→Running 状態:Ready 状態のプロセスがスケジュールされた後、プロセッサ リソースを取得する (プロセッサ タイム スライスを割り当てる) ため、プロセスは Ready 状態から Running 状態に変化します。
- 実行状態 → 準備完了状態: 実行状態のプロセスは、タイム スライスが使い果たされた後、プロセッサを放棄する必要があるため、プロセスは実行状態から準備完了状態に変換されます。さらに、プリエンプティブル オペレーティング システムでは、優先度の高いプロセスが実行可能になると、スケジューラは実行中のプロセスを準備完了状態に遷移させ、優先度の高いプロセスを実行できるようにします。
- 実行中状態 → ブロッキング状態: プロセスがリソース (周辺機器など) の使用と割り当てを要求するか、イベントの発生 (I/O 操作の完了など) を待機すると、実行中状態から次の状態に遷移します。ブロッキング状態。このプロセスは、システム コールの形式でサービスを提供するようオペレーティング システムに要求します。システム コールは、ユーザー モード プログラムを実行してオペレーティング システムのカーネル プロセスを呼び出す形式です。
- ブロッキング状態 → 準備完了状態: プロセスが I/O 操作の終了や割り込みの終了などのイベントの到着を待機している場合、割り込みハンドラーは、対応するプロセスの状態をブロック状態からブロック状態に変更する必要があります。準備完了状態。
2. 6 つの州
これはJava APIレベルから記述されます。
Thread.State 列挙によると、6 つの状態に分けられます。
- NEW スレッドが作成されたばかりですが、start() メソッドはまだ呼び出されていません
- RUNNABLE start() メソッドを呼び出した後、Java API レベルでの RUNNABLE 状態は、オペレーティング システム レベルでの [runnable state]、[running state]、および [blocked state] をカバーすることに注意してください (Java では、BIO によって引き起こされるスレッド ブロッキング。 、まだ実行可能と見なされます)
- BLOCKED 、 WAITING 、 TIMED_WAITING はすべて、Java API レベルでの [ブロッキング状態] の下位区分です。これについては、後の状態遷移セクションで詳しく説明します。
- スレッド コードの実行が終了すると TERMINATED
Thread.State は、6 つの列挙定数を定義する内部列挙クラスです。
public enum State {
// 新建状态
NEW,
// 运行状态
RUNNABLE,
/**
* 阻塞状态
* Object.wait
*/
BLOCKED,
/**
* 等待状态
* Object.wait
* Thread.join
* LockSupport.park
*/
WAITING,
/**
* 限时等待状态
* Thread.sleep
* Object.wait
* Thread.join
* LockSupport.parkUntil
* LockSupport.parkNanos
*/
TIMED_WAITING,
// 终止状态
TERMINATED;
}
Java で状態を確認する
@Slf4j(topic = "c.threadState")
public class ThreadState {
public static void main(String[] args) throws IOException {
Thread t1 = new Thread("t1") {
@Override
public void run() {
log.debug("running...");
}
};
Thread t2 = new Thread("t2") {
@Override
public void run() {
while(true) {
// runnable
}
}
};
t2.start();
Thread t3 = new Thread("t3") {
@Override
public void run() {
log.debug("running...");
}
};
t3.start();
Thread t4 = new Thread("t4") {
@Override
public void run() {
synchronized (ThreadState.class) {
try {
Thread.sleep(1000000); // timed_waiting
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t4.start();
Thread t5 = new Thread("t5") {
@Override
public void run() {
try {
t2.join(); // waiting
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t5.start();
Thread t6 = new Thread("t6") {
@Override
public void run() {
synchronized (ThreadState.class) {
// blocked
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t6.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("t1 state {}", t1.getState());
log.debug("t2 state {}", t2.getState());
log.debug("t3 state {}", t3.getState());
log.debug("t4 state {}", t4.getState());
log.debug("t5 state {}", t5.getState());
log.debug("t6 state {}", t6.getState());
System.in.read();
}
}
出力:
17:46:11.509 [t3] DEBUG c.threadState - running...
17:46:12.008 [main] DEBUG c.threadState - t1 state NEW
17:46:12.016 [main] DEBUG c.threadState - t2 state RUNNABLE
17:46:12.017 [main] DEBUG c.threadState - t3 state TERMINATED
17:46:12.017 [main] DEBUG c.threadState - t4 state TIMED_WAITING
17:46:12.017 [main] DEBUG c.threadState - t5 state WAITING
17:46:12.017 [main] DEBUG c.threadState - t6 state BLOCKED
さまざまな状況での Java の 6 つの状態の遷移を分析してみましょう
スレッドがあるとします
Thread t
ケース1NEW --> RUNNABLE
t.start()
メソッドを呼び出す場合はNEW --> RUNNABLE で
ケース 2RUNNABLE <--> WAITING
t スレッドがオブジェクト ロックをsynchronized(obj)
取得した後、
obj.wait()
メソッドが呼び出されると、 t スレッドはRUNNABLE --> WAITING
- コール
obj.notify()
、_obj.notifyAll()
の場合t.interrupt()
- 競合ロックが成功し、t スレッドが
WAITING --> RUNNABLE
- 競合したロックの失敗、t スレッドから
WAITING --> BLOCKED
- 競合ロックが成功し、t スレッドが
public class TestWaitNotify {
final static Object obj = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (obj) {
log.debug("执行....");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("其它代码...."); // 断点
}
},"t1").start();
new Thread(() -> {
synchronized (obj) {
log.debug("执行....");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("其它代码...."); // 断点
}
},"t2").start();
TimeUnit.MILLISECONDS.sleep(500);
log.debug("唤醒 obj 上其它线程");
synchronized (obj) {
obj.notifyAll(); // 唤醒obj上所有等待线程 断点
}
}
}
ケース 3RUNNABLE <--> WAITING
- 現在のスレッドが
t.join()
メソッドを呼び出すと、現在のスレッドは から開始されRUNNABLE --> WAITING
ます現在のスレッドはtスレッド オブジェクトのモニターで待機していることに注意してください - t スレッドが実行を終了するか、現在のスレッドの interrupt()を呼び出すと、現在のスレッドは
WAITING --> RUNNABLE
ケース4RUNNABLE <--> WAITING
- 現在のスレッドで
LockSupport.park()
メソッド現在のスレッドがRUNNABLE --> WAITING
LockSupport.unpark
(ターゲット スレッド)を呼び出すか、スレッドを呼び出すとinterrupt()
、ターゲット スレッドがから作成されます。WAITING --> RUNNABLE
ケース5RUNNABLE <--> TIMED_WAITING
t スレッドがオブジェクト ロックをsynchronized(obj)
取得した後、
obj.wait(long n)
メソッドが呼び出されると、 t スレッドはRUNNABLE --> TIMED_WAITING
- t スレッドがn ミリ秒を超えて待機するか、
obj.notify()
、obj.notifyAll()
、t.interrupt()
- 競合ロックが成功し、t スレッドが
TIMED_WAITING --> RUNNABLE
- 競合したロックの失敗、t スレッドから
TIMED_WAITING --> BLOCKED
- 競合ロックが成功し、t スレッドが
状況 6RUNNABLE <--> TIMED_WAITING
- 現在のスレッドが
t.join(long n)
メソッドを呼び出すと、現在のスレッドは から開始されRUNNABLE --> TIMED_WAITING
ます現在のスレッドはt スレッドオブジェクトのモニターで待機していることに注意してください - 現在のスレッドがn ミリ秒を超えて待機するか、t スレッドが実行を終了するか、現在のスレッドのを呼び出すと、現在のスレッドは
interrupt()
TIMED_WAITING --> RUNNABLE
ケース7RUNNABLE <--> TIMED_WAITING
- 現在のスレッドによって呼び出され
Thread.sleep(long n)
、現在のスレッドは次から始まりますRUNNABLE --> TIMED_WAITING
- 現在のスレッドの待機時間が n ミリ秒を超えています。
TIMED_WAITING --> RUNNABLE
ケース8RUNNABLE <--> TIMED_WAITING
- 現在のスレッドが
LockSupport.parkNanos(long nanos)
またはを呼び出すとLockSupport.parkUntil(long millis)
、現在のスレッドはRUNNABLE --> TIMED_WAITING
- (ターゲット スレッド)を呼び出す
LockSupport.unpark
か、 thread を呼び出すかinterrupt()
、またはtimeout を待機すると、ターゲット スレッドがTIMED_WAITING--> RUNNABLE
状況 9RUNNABLE <--> BLOCKED
- tスレッドがオブジェクトロック
synchronized(obj)
を取得するときに競合が失敗した場合RUNNABLE --> BLOCKED
- obj-locked スレッドの同期コード ブロックの実行が完了すると、オブジェクト上の
BLOCKED
すべての.スレッド t が競合に成功した場合、BLOCKED --> RUNNABLE
他の失敗したスレッドは引き続きBLOCKED
ケース10RUNNABLE <--> TERMINATED
- 現在のスレッドのすべてのコードの実行が終了したら、次のように入力します。
TERMINATED