まず、Javaスレッドの状態
Javaでは、マルチスレッドはスレッドのコアコンセプトによって駆動されます。スレッドは、その存続期間中にさまざまな状態を経ます。
java.lang.Threadクラスには、静的な状態列挙が含まれています。これは、スレッドの状態を定義します。次の状態が含まれます。
NEW-まだ実行を開始していない新しく作成されたスレッド
RUNNABLE –実行中または実行の準備ができていますが、リソースの割り当てを待機しています
BLOCKED –同期されたブロック/メソッドに入るまたは再入るためのモニターロックの取得を待機しています
待機中–他のスレッドが時間制限なしで特定のアクションを実行するのを待機します
TIMED_WAITING –他のスレッドが指定された期間内に特定のアクションを実行するのを待ちます
終了–実行が完了しました
1、NEW
NEWスレッドは、作成されたがまだ開始されていないスレッドです。start()メソッドで開始されるまでその状態を維持します。
次のコードは、NEW状態で新しく作成されたスレッドを示しています。
Runnable runnable = new NewState();
Thread t = new Thread(runnable);
System.out.println("Show:" + t.getState());
2、実行可能
新しいスレッドを作成し、そのスレッドでstart()メソッドを呼び出すと、NEW状態からRUNNABLE状態に移行します。この状態のスレッドは実行中または実行準備ができていますが、システムがリソースを割り当てるのを待機しています。
マルチスレッド環境では、スレッドスケジューラ(JVMの一部)は各スレッドに一定の時間を割り当てます。したがって、特定の時間実行されてから、他のRUNNABLEスレッドに制御を与えます。
以下のコードは、おそらくRUNNABLEを出力しますが、 t.getState()が実行されたときにまだRUNNABLE状態であるという保証はありません。スレッドスケジューラによってすぐにスケジュールされ、実行が完了する場合があります。この場合、異なる出力が得られる可能性があります。
Runnable runnable = new NewState();
Thread t = new Thread(runnable);
t.start();
System.out.println("Show:" + t.getState());
3、ブロック
スレッドが現在実行に適格でない場合、スレッドはBLOCKED状態になります。モニターがロックされるのを待って、別のスレッドによってロックされているコードにアクセスしようとしている間、この状態になります。
以下のコードを参照してください。
(1)2つのスレッドt1とt2が作成されます。
(2)t1が開始し、同期されたcommonResource()メソッドに入ります。これは、1つのスレッドのみがアクセスできることを意味します。このメソッドにアクセスしようとする他のすべての後続スレッドは、現在のスレッドが処理を終了するまで、それ以上の実行がブロックされます。
(3)t1がこのメソッドに入るとき、それは無限のwhileループにあります。これは、他のすべてのスレッドがメソッドに入ることができないように、集中的な計算をシミュレートするためだけのものです。
(3)t2を開始すると、t1によってアクセスされたcommonResource()メソッドに入ろうとするため、t2はBLOCKED状態のままになり ます。
public class BlockedState {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new DemoThreadB());
Thread t2 = new Thread(new DemoThreadB());
t1.start();
t2.start();
Thread.sleep(1000);
Log.info(t2.getState());
System.exit(0);
}
}
class DemoThreadB implements Runnable {
@Override
public void run() {
commonResource();
}
public static synchronized void commonResource() {
while(true) {
// Infinite loop to mimic heavy processing
// 't1' won't leave this method
// when 't2' try to enter this
}
}
}
4、待っています
他のスレッドが特定の操作を実行するのを待っている間、スレッドはWAITING状態にあります。JavaDocsによると、次の3つのメソッドのいずれかを呼び出すことにより、どのスレッドもこの状態に入ることができます。
wait()、thread.join()、LockSupport.park()
次のコードを参照してください。
(1)t1を作成して開始しました
(2)t1はt2を作成し、それを開始します
(3)t2が処理を続行する場合、t2.join()を呼び出します。これにより、t2の実行が終了するまでt1がWAITING状態になります。
(4)t1はt2の完了を待機しているため、t2からt1.getState()を呼び出し、状態はWAITINGを出力します。
public class WaitingState implements Runnable {
public static Thread t1;
public static void main(String[] args) {
t1 = new Thread(new WaitingState());
t1.start();
}
public void run() {
Thread t2 = new Thread(new DemoThreadWS());
t2.start();
try {
t2.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Log.error("Thread interrupted", e);
}
}
}
class DemoThreadWS implements Runnable {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Log.error("Thread interrupted", e);
}
Log.info(WaitingState.t1.getState());
}
}
5、TIMED_WAITING
スレッドは、別のスレッドが特定の操作を指定された時間実行するのを待つときに、TIMED_WAITING状態になります。
JavaDocsによると、スレッドをTIMED_WAITING状態にする方法は5つあります。
thread.sleep(ロングミリ秒)
wait(intタイムアウト)またはwait(intタイムアウト、int nanos)
thread.join(ロングミリ秒)
LockSupport.parkNanos
LockSupport.parkUntil
次のコードを参照すると、スレッドt1が作成されて開始され 、5秒のタイムアウトでスリープ状態になります。出力はTIMED_WAITINGになります。
public class TimedWaitingState {
public static void main(String[] args) throws InterruptedException {
DemoThread obj1 = new DemoThread();
Thread t1 = new Thread(obj1);
t1.start();
// The following sleep will give enough time for ThreadScheduler
// to start processing of thread t1
Thread.sleep(1000);
Log.info(t1.getState());
}
}
class DemoThread implements Runnable {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Log.error("Thread interrupted", e);
}
}
}
6、終了
これはデッドスレッドの状態です。実行が終了するか、異常終了すると、TERMINATED状態になります。
次のコードを参照すると、スレッドt1を開始すると、次のステートメントThread.sleep(1000)はt1に完了するのに十分な時間を与えるため、このプログラムは次の出力を提供します。TERMINATED。
public class TerminatedState implements Runnable {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new TerminatedState());
t1.start();
// The following sleep method will give enough time for
// thread t1 to complete
Thread.sleep(1000);
Log.info(t1.getState());
}
@Override
public void run() {
// No processing in this block
}
}
スレッドの状態に加えて、isAlive()メソッドを使用して、スレッドが生きているかどうかを判断することもできます。たとえば、このスレッドでisAlive()メソッドを呼び出すと、falseも返されます。結論として、スレッドは、開始されて死んでいない場合にのみ生きています。
Log.info(t1.isAlive());
2.まとめ
Javaスレッドを使用してマルチスレッド環境でプログラミングする場合、Javaのスレッドサイクルとスレッドの状態を理解することが重要です。