日々のマルチスレッド開発では、CPU にランダムにスケジュールを設定するのではなく、各スレッドを指定した順序で実行したい場合があります。日々の開発作業に無用なトラブルを引き起こす可能性があります。
この要件があるため、この記事のタイトルは、スレッドが指定された順序で実行できるようにするために導入されました。
興味のある学生は、次のコードの考えられる結果を推測できます:
通常の理解によれば、上記のコードを実行すると、 code シーケンスは t1 → t2 → t3 である必要がありますが、実際の効果は理想的ではありません。
下の図は、実行中の効果を示しています。
結合は、人によっては簡単ではないかもしれません。学生の方 ここでは Join について詳しく説明しませんので、分からない方は baidu や Google で調べてください。
ここでは、join を使用して目的の効果を実現する方法を直接紹介します。
ここでは、主に Join のブロック効果を使用して目的を達成します。上図の実行結果を見ると、プログラムが指定した順序で実行され、期待した結果が得られたことがわかります。
実際、結合によってなぜ望ましい効果が得られるのかを深く考えることができます。次に、ソース コードを見てみましょう:
結合ソース コードを入力すると、最初に 0 パラメーターを渡す結合メソッドが表示されます。ここで、入力を続けることを選択します。
第一に、結合メソッドがスレッドセーフであることがわかります。第二に、上の図と合わせて確認できます。入力パラメータが 0 の場合、 wait(0) がヒットします。この方法は、経験豊富な学生であれば直接理解できるはずですが、ここでは待つことを意味します。
ただし、ここでの待機は呼び出し元を待機しているのではなく、ブロックされたメイン スレッドを待機していることに注意してください。t1、t2、および t3 は単なるサブスレッドです。サブスレッドの実行が終了すると、メインスレッドは待機を終了します。
これは結合がどのように機能するかを示し、また結合によってプログラムで望む結果を達成できることを証明しています。
プログラム内のスレッドの順序を制御するのに役立つ結合に加えて、他の方法もあります。たとえば、スレッド プールを使用してみましょう。
Executor は、JDK の java.util.concurrent パッケージにあるスレッド プール操作クラスであり、スレッド プール操作を簡単に提供できます。
ここでは、Executor の newSingleThreadExecutor() メソッドを使用して、シングルスレッド スレッド プールを作成します。
上の図からわかるように、newSingleThreadExecutor() メソッドを使用しても期待どおりの結果を達成できます。実際、原理は非常に単純です。は FIFO ベースのキューです。つまり、t1、t2、t3 を順番にキューに追加すると、実際にはスレッド t1 のみが準備完了状態になり、t2 と t3 がキューに追加されます。 t1 が完了すると、キュー内の他のスレッドの実行が続行されます。
演算子を学習するとき、読者は各演算子間に優先順位があることを知ります。演算子の優先順位を理解することは、プログラム開発に非常に役立ちます。スレッドについても同様で、各スレッドには優先順位があり、Java 仮想マシンはスレッドの優先順位に基づいてスレッドの実行順序を決定するため、複数のスレッドが競合することなく CPU リソースを合理的に共有できます。
Java 言語では、スレッドの優先順位の範囲は 1 ~ 10 であり、値は 1 ~ 10 である必要があり、そうでない場合は例外が発生します。デフォルト値は です。優先度は5です。優先度の高いスレッドが最初に実行され、実行が完了すると、優先度の低いスレッドが実行されます。優先順位が同じ場合は、順番に実行されます。
Thread クラスの setPriority() メソッドを使用して、スレッドの優先順位を設定できます。構文は次のとおりです。
public final void setPriority(int newPriority);
現在のスレッドの優先順位を取得したい場合は、 getPriority() メソッドを直接呼び出すことができます。構文は次のとおりです。
public final int getPriority();
優先順位を簡単に理解した後、簡単な例を使用して優先順位の使用方法を示します。
例 1
Thread クラスと Runnable インターフェイスを使用して、それぞれスレッドを作成し、それらに優先順位を割り当てます。
public class FirstThreadInput extends Thread { public void run() { System.out.println("调用FirstThreadInput类的run()重写方法"); //输出字符串 for(int i=0;i<5;i++) { System.out.println("FirstThreadInput线程中i="+i); //输出信息 try { Thread.sleep((int) Math.random()*100); //线程休眠 } catch(Exception e){} } } }
(2) Runnable インターフェイスを実装し、run() メソッドを実装する SecondThreadInput クラスを作成します。コードは以下のように表示されます:
public class SecondThreadInput implements Runnable { public void run() { System.out.println("调用SecondThreadInput类的run()重写方法"); //输出字符串 for(int i=0;i<5;i++) { System.out.println("SecondThreadInput线程中i="+i); //输出信息 try { Thread.sleep((int) Math.random()*100); //线程休眠 } catch(Exception e){} } } }
(3) 创建 TestThreadInput 测试类,分别使用 Thread 类的子类和 Runnable 接口的对象创建线程,然后调用 setPriority() 方法将这两个线程的优先级设置为 4,最后启动线程。代码如下:
public class TestThreadInput { public static void main(String[] args) { FirstThreadInput fti=new FirstThreadInput(); Thread sti=new Thread(new SecondThreadInput()); fti.setPriority(4); sti.setPriority(4); fti.start(); sti.start(); } }
(4) 运行上述代码,运行结果如下所示。
调用FirstThreadInput类的run()重写方法
调用SecondThreadInput类的run()重写方法
FirstThreadInput线程中i=0
SecondThreadInput线程中i=0
FirstThreadInput线程中i=1
FirstThreadInput线程中i=2
SecondThreadInput线程中i=1
FirstThreadInput线程中i=3
SecondThreadInput线程中i=2
FirstThreadInput线程中i=4
SecondThreadInput线程中i=3
SecondThreadInput线程中i=4
由于该例子将两个线程的优先级都设置为 4,因此它们交互占用 CPU ,宏观上处于并行运行状态。
重新更改 ThreadInput 类的代码、设置优先级。代码如下:
fti.setPriority(1); sti.setPriority(10);
重新运行上述代码,如下所示。
调用FirstThreadInput类的run()重写方法
调用SecondThreadInput类的run()重写方法
FirstThreadInput线程中i=0
SecondThreadInput线程中i=0
SecondThreadInput线程中i=1
SecondThreadInput线程中i=2
SecondThreadInput线程中i=3
SecondThreadInput线程中i=4
FirstThreadInput线程中i=1
FirstThreadInput线程中i=2
FirstThreadInput线程中i=3
FirstThreadInput线程中i=4
以上がJavaでスレッドを自分で指定した順序で実行する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。