1. Java でマルチスレッド プログラムを作成するのは、他のプログラミング言語よりもはるかに簡単です。主に Runnable インターフェイスと Thread クラスを通じて実装されます。
publicclassSimpleRunnable implements Runnable{ private String message; publicstaticvoid main(String[] args) { SimpleRunnabler1 = new SimpleRunnable("Hello"); Threadt1 = new Thread(r1); t1.start(); for(;;){ System.out.println("Bye-bye"); } } public SimpleRunnable(String message){ this.message = message; } @Override publicvoid run() { for(;;){ System.out.println(message); } } }
上記では、Runable インターフェースを継承して run() を実装することでマルチスレッドを実装し、Thread を通じて仮想 CPU を実装し、スレッド r1 を独立したスレッドで実行できるようにしています。実際には、このスレッドとメインスレッドは完全に独立したスレッドではなく、r1 スレッドとメインスレッドが切り替わって実行されます。ただし、切り替え速度は非常に速く、2 つのスレッドが独立して実行されているように見えます。
2. スレッドの切り替えは、オペレーティング システムによって異なります。
1 つは、スレッドが CPU を獲得した場合、そのスレッドが実行を終了するか、受動的に停止されるまで起動されません。
1 つは優先モードを使用し、最も高い優先順位を持つスレッドが最初に CPU を取得します。
1 つはタイム スライスです。タイム スライスの実行後にスレッドが終了すると、他のスレッドが CPU を占有する可能性がかなり高くなります。
Java のスレッドは、優先順位とタイム スライスに基づいた包括的なアプローチを採用しています。具体的な実装は、実行されているオペレーティング システムによって異なります。たとえば、スレッドはタイム スライスの実行を終了すると終了し、優先順位を 1 レベル下げます。その後、より高い優先順位のスレッドがプロセスの実行中に来た場合、CPU を占有します。現在のCPUを占有します。
3、スレッド実行ステータス:
スレッド停止 (Pause) には、sleep()、wait()、suspend()、I/O ブロックが含まれます
スレッド再起動 (Run) には、スリープ タイムアウト、notify() が含まれます、resume()、I/O終了
スレッド終了、stop()
スレッド待機、join()
スレッドは積極的にCPUを放棄、yield()
suspend()、resume()、stop()以上すべて廃止され、推奨されなくなりました。
4、sleep() 関数は静的であり、オブジェクトではなくクラスに属する関数です。この関数は、他のスレッドを停止するのではなく、呼び出し元のスレッドを一定期間一時停止させます。以下の通り
publicstaticvoidmain(String[] args)throwsException { SimpleRunnabler1 = new SimpleRunnable("Hello"); Threadt1 = newThread(r1); t1.start(); for(inti = 0; i < 10; i++){ System.out.println("Bye-bye"); } t1.sleep(10000); t1.stop(); }
上記のコードは、t1 を 10 秒間停止するのではなく、メインスレッドを 10 秒間停止します。さらに、sleep() はスレッドをファジー値のために一時停止させます。ただし、スレッドの切り替えが不確実であるため、メインスレッドは正確に 10 秒間一時停止しません。 。
5. もう 1 つの静的関数は yield() です。これは、上記の sleep() 関数と同様に、この関数は現在実行中のスレッドでのみ動作できることを意味します。
6. プログラミングとは効率的な結果を追求し、マルチスレッドを使用することです。ただし、マルチスレッド操作は予測が難しいため、マルチスレッド操作の結果をできるだけ予測しやすくするために、特定の方法を採用します。
class Thread1 extends Thread{ @Override publicvoid run(){ try{ System.out.println("thread1 start"); sleep(10000); // <3> System.out.println("thread1 finish");//<4> }catch(Exception e){ } } } class Thread2 extends Thread{ @Override publicvoid run(){ try{ System.out.println("thread2 start"); suspend(); // <2> System.out.println("thread2 finish");// <7> }catch(Exception e){ } } } publicclassThreadTest { publicstaticvoid main(String[] args) { Threadt1 = new Thread1(); Thread2t2 = new Thread2(); t1.start(); t2.start(); try{ System.out.println("s1"); t1.join(); // <1> System.out.println("s2"); // <5> t2.resume(); //<6> System.out.println("s3"); // <8> t2.join(); // <9> }catch(Exception e){ } System.out.println("s4"); // <10> } }
、でも毎回ではありませんこのようにして結果を取得します。しかし、その一部は予測可能です。どれが予測可能ですか?どれが予測不可能ですか? (1) 最初の 3 行は必ず最初の 3 行を占めます。<1> のコードはメインスレッドを停止してスレッド t1 の終了を待つため、t1 スレッドは < でスレッドを 10 秒間一時停止します。 3>. のコードは、スレッドをウェイクアップするコードが存在するまでスレッド t2 が停止状態にあることを示します。そうでない場合、スレッドはブロックされたままになります。ただし、最初の 3 行の出力順序は予測できません。 (2) 4 行目は t1 のスリープが終了したら、最初に のコードを実行します。スレッドが終了し、メイン スレッドが CPU を取得し、コード の実行を開始します(4) コード がスレッド t2 を起動すると、実行が開始されます。 から、同時にメインスレッド を実行し続けます(5) 最後の行は必ず最後の行になります。 でメインスレッドを一時停止し、t2 の終わりを待ち、 を実行して最後の行を出力すると、メインスレッドが終了して終了します。