人が生まれ、老い、病気になり、死ぬのと同じように、スレッドも開始 (待機)、実行、中断、停止という 4 つの異なる状態を経る必要があります。これら 4 つの状態は、Thread クラスのメソッドを通じて制御できます。 Thread クラスのこれら 4 つの状態に関連するメソッドを以下に示します。
// 开始线程 public void start( ); public void run( ); // 挂起和唤醒线程 public void resume( ); // 不建议使用 public void suspend( ); // 不建议使用 public static void sleep(long millis); public static void sleep(long millis, int nanos); // 终止线程 public void stop( ); // 不建议使用 public void interrupt( ); // 得到线程状态 public boolean isAlive( ); public boolean isInterrupted( ); public static boolean interrupted( ); // join方法 public void join( ) throws InterruptedException;
1. スレッドを作成して実行します
スレッドは確立直後に run メソッド内のコードを実行せず、待機状態になります。スレッドが待機状態にある場合、Thread クラスのメソッドを通じて、スレッドの優先順位 (setPriority)、スレッド名 (setName)、スレッド タイプ (setDaemon) などのスレッドのさまざまな属性を設定できます。
start メソッドが呼び出されると、スレッドは run メソッド内のコードの実行を開始します。スレッドは実行状態になります。 Thread クラスの isAlive メソッドを使用して、スレッドが実行されているかどうかを確認できます。スレッドが実行状態にある場合、isAlive は true を返します。isAlive が false を返す場合、スレッドは待機状態または停止状態にある可能性があります。次のコードは、スレッドの作成、実行、停止の 3 つの状態間の切り替えを示し、対応する isAlive 戻り値を出力します。
package chapter2; public class LifeCycle extends Thread { public void run() { int n = 0; while ((++n) < 1000); } public static void main(String[] args) throws Exception { LifeCycle thread1 = new LifeCycle(); System.out.println("isAlive: " + thread1.isAlive()); thread1.start(); System.out.println("isAlive: " + thread1.isAlive()); thread1.join(); // 等线程thread1结束后再继续执行 System.out.println("thread1已经结束!"); System.out.println("isAlive: " + thread1.isAlive()); } }
上記のコードでは join メソッドが使用されていることに注意してください。このメソッドの主な機能は、スレッドの run メソッドが完了した後もプログラムが確実に実行されるようにすることです。このメソッドは後の記事で紹介します
。
上記のコードの実行結果:
isAlive: false isAlive: true thread1已经结束! isAlive: false
2. スレッドを一時停止してウェイクアップします
スレッドが run メソッドの実行を開始すると、run メソッドが完了するまでスレッドは終了しません。ただし、スレッドの実行中に、2 つの方法でスレッドの実行を一時的に停止できます。これら 2 つのメソッドは、suspend と sleep です。suspend を使用してスレッドを一時停止した後、resume メソッドを使用してスレッドをウェイクアップできます。 sleep を使用してスレッドをスリープ状態にした後、スレッドは設定された時間が経過した後にのみ準備完了状態になることができます (スレッドのスリープ終了後、スレッドはすぐには実行されない場合がありますが、システムがスケジュールするのを待って準備完了状態になるだけです)。 。
サスペンドとレジュームはスレッドを簡単にサスペンドしたりウェイクアップしたりできますが、これら 2 つのメソッドを使用すると、予期せぬ事態が発生する可能性があります。そのため、これら 2 つのメソッドは非推奨 (抗議) としてマークされており、これらの 2 つのメソッドは将来の JDK で削除される可能性があることを示しています。バージョンが異なるため、これら 2 つの方法を使用してスレッドを操作しないようにしてください。次のコードは、sleep、suspend、resume メソッドの使用を示しています。
package chapter2; public class MyThread extends Thread { class SleepThread extends Thread { public void run() { try { sleep(2000); } catch (Exception e) { } } } public void run() { while (true) System.out.println(new java.util.Date().getTime()); } public static void main(String[] args) throws Exception { MyThread thread = new MyThread(); SleepThread sleepThread = thread.new SleepThread(); sleepThread.start(); // 开始运行线程sleepThread sleepThread.join(); // 使线程sleepThread延迟2秒 thread.start(); boolean flag = false; while (true) { sleep(5000); // 使主线程延迟5秒 flag = !flag; if (flag) thread.suspend(); else thread.resume(); } } }
スリープとサスペンドの使用の効果は表面的には似ていますが、スリープ メソッドはサスペンドと同等ではありません。それらの最大の違いは、あるスレッドでサスペンド メソッドを使用して別のスレッドをサスペンドできることです。上記のコードでは、メインスレッドでスレッドが一時停止されます。スリープは、現在実行中のスレッドでのみ機能します。上記のコードでは、sleepThread とメイン スレッドはそれぞれ 2 秒と 5 秒スリープします。スリープを使用する場合は、あるスレッドを別のスレッドでスリープさせることはできないことに注意してください。たとえば、main メソッドで thread.sleep(2000) メソッドを使用すると、スレッド thread を 2 秒間スリープさせることはできませんが、メイン スレッドを 2 秒間スリープさせることしかできません。
スリープメソッドを使用する際の注意点は次の 2 つです:
1. sleep メソッドには 2 つのオーバーロード形式があり、そのうちの 1 つはミリ秒だけでなくナノ秒 (1,000,000 ナノ秒は 1 ミリ秒に等しい) も設定できます。ただし、ほとんどのオペレーティング システム プラットフォームの Java 仮想マシンはナノ秒まで正確ではないため、スリープにナノ秒が設定されている場合、Java 仮想マシンはこの値に最も近いミリ秒を取得します。
2. sleep メソッドを使用する場合は、throws または try{...}catch{...} を使用する必要があります。run メソッドでは throws を使用できないため、try{...}catch{...} のみを使用できます。スレッドがスリープしている場合、割り込みメソッドを使用してスレッドを中断すると、Sleep は InterruptedException をスローします (このメソッドについては 2.3.3 で説明します)。 sleep メソッドは次のように定義されます:
1 public static void sleep(long millis) throws InterruptedException 2 public static void sleep(long millis, int nanos) throws InterruptedException
3. スレッドを終了する 3 つの方法
スレッドを終了するには 3 つの方法があります。
1. 終了フラグを使用して、スレッドを正常に終了します。つまり、run メソッドが完了するとスレッドが終了します。
2. stop メソッドを使用してスレッドを強制的に終了します (サスペンドや再開と同様に停止も予期しない結果を引き起こす可能性があるため、この方法はお勧めできません)。
3. スレッドを中断するには、interrupt メソッドを使用します。
1. 終了フラグを使用してスレッドを終了します
当run方法执行完后,线程就会退出。但有时run方法是永远不会结束的。如在服务端程序中使用线程进行监听客户端请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如while循环。如果想让循环永远运行下去,可以使用while(true){……}来处理。但要想使while循环在某一特定条件下退出,最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环是否退出。下面给出了一个利用退出标志终止线程的例子。
package chapter2; public class ThreadFlag extends Thread { public volatile boolean exit = false; public void run() { while (!exit); } public static void main(String[] args) throws Exception { ThreadFlag thread = new ThreadFlag(); thread.start(); sleep(5000); // 主线程延迟5秒 thread.exit = true; // 终止线程thread thread.join(); System.out.println("线程退出!"); } }
在上面代码中定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false.在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值,
2. 使用stop方法终止线程
使用stop方法可以强行终止正在运行或挂起的线程。我们可以使用如下的代码来终止线程:
1 thread.stop();
虽然使用上面的代码可以终止线程,但使用stop方法是很危险的,就象突然关闭计算机电源,而不是按正常程序关机一样,可能会产生不可预料的结果,因此,并不推荐使用stop方法来终止线程。
3. 使用interrupt方法终止线程
使用interrupt方法来终端线程可分为两种情况:
(1)线程处于阻塞状态,如使用了sleep方法。
(2)使用while(!isInterrupted()){……}来判断线程是否被中断。
在第一种情况下使用interrupt方法,sleep方法将抛出一个InterruptedException例外,而在第二种情况下线程将直接退出。下面的代码演示了在第一种情况下使用interrupt方法。
package chapter2; public class ThreadInterrupt extends Thread { public void run() { try { sleep(50000); // 延迟50秒 } catch (InterruptedException e) { System.out.println(e.getMessage()); } } public static void main(String[] args) throws Exception { Thread thread = new ThreadInterrupt(); thread.start(); System.out.println("在50秒之内按任意键中断线程!"); System.in.read(); thread.interrupt(); thread.join(); System.out.println("线程已经退出!"); } }
上面代码的运行结果如下:
在50秒之内按任意键中断线程! sleep interrupted 线程已经退出!
在调用interrupt方法后, sleep方法抛出异常,然后输出错误信息:sleep interrupted.
注意:在Thread类中有两个方法可以判断线程是否通过interrupt方法被终止。一个是静态的方法interrupted(),一个是非静态的方法isInterrupted(),这两个方法的区别是interrupted用来判断当前线是否被中断,而isInterrupted可以用来判断其他线程是否被中断。因此,while (!isInterrupted())也可以换成while (!Thread.interrupted())。
以上就是java线程之线程的生命周期的使用的内容,更多相关内容请关注PHP中文网(www.php.cn)!