私の理解では、理論的にはスレッドは並行して実行されます。JVMが決定します。待機中のスレッドキューからどのスレッドを選択するか(アルゴリズムに基づく)リソースが利用可能な場合。
したがって、スレッドの実行シーケンスを提供/強制することはできません。
私のJavaアプリケーションにt1、t2、t3の3つのスレッドがあるとします。
いくつかの特定の理由で; スレッドをt3、t1、t2の順に実行したいと思います。
これを行うことは可能ですか?Javaはこれを行う方法を提供しましたか?
私の理解では、理論的にはスレッドは並行して実行されます。JVMが決定します。待機中のスレッドキューからどのスレッドを選択するか(アルゴリズムに基づく)リソースが利用可能な場合。
したがって、スレッドの実行シーケンスを提供/強制することはできません。
私のJavaアプリケーションにt1、t2、t3の3つのスレッドがあるとします。
いくつかの特定の理由で; スレッドをt3、t1、t2の順に実行したいと思います。
これを行うことは可能ですか?Javaはこれを行う方法を提供しましたか?
Executor を使用します。
executor.execute(runnable1);
wait();
executor.execute(runnable2);
wait();
executor.execute(runnable3);
wait();
そしてもちろん、各 Runnable はnotify()
ステートメントで終了する必要があります。
スレッドを使用しないでください、簡単な答えです。
コードが順不同で実行されることを望まないのであれば、なぜスレッドを使用しているのですか? 通常どおり、ステップごとに実行するだけです。
スレッドの特定の部分を順番に実行する場合は、ロック、待機/通知、セマフォなどの標準的な同時実行メカニズムを使用しますが、操作全体を特定の順序で実行するだけの場合は、それらを順番に実行します. スレッドなし。
Java 8以降、これは次を使用して非常に簡単になりましたCompletableFuture
:
CompletableFuture.runAsync(runnable3)
.thenRunAsync(runnable1)
.thenRunAsync(runnable2);
私はあなたの状況をモデル化しようとしました:
public class ThreadJoinExample {
private static final Thread FIRST = new Thread( new RunnableImpl(), "first" );
private static final Thread SECOND = new Thread( new RunnableImpl(), "second" );
public static void main(String[] args) {
//here have started current thread or "main" thread that will control above threads
FIRST.start();
//waiting 2 seconds, "stop" your current thread and after current thread will start this "t3" thread until it will dead
try {
FIRST.join(2000);
} catch (InterruptedException e) {
System.out.println();
e.printStackTrace();
}
SECOND.start();
//"stop" your current thread immediately and run "t1" thread until it will dead.
try {
SECOND.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
//Or we can wait for all threads and in the end - finish current main thread
try {
FIRST.join();
SECOND.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Current thread is going die");
}
}
class RunnableImpl implements Runnable{
@Override
public void run() {
System.out.println("Started thread: "+Thread.currentThread().getName());
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread is going die: "+Thread.currentThread().getName());
}
}
出力:
Started thread: first
Started thread: second
Thread is going die: first
Thread is going die: second
Current thread is going die
要約: .join ()メソッドを使用すると、「結合されたスレッド」が停止するまで、現在のスレッドを Runnable 状態に移行できます
別のスレッドに参加して、別のスレッドが終了したときに彼が実行されるようにすることができます。
スレッドを実行する順序をスレッド スケジューラに伝えることはできません。スレッド A で実行されている特定のコードを、スレッド B で実行されている別のコードの前に実行する必要がある場合は、ロックまたはwait()
/ notify()
.
たとえば、両方のスレッドからアクセス可能な変数を「フラグ」として使用して、スレッド B が安全に処理できるかどうかを示すことができます。スレッド B はwait()
ループ内で、その変数の値をチェックする可能性があります。その後、スレッド B が安全に実行できるようになったら、スレッド A は変数を設定し、 を使用してスレッド B をウェイクアップできますnotify()
。
そうです、異なるスレッドで発生することの間に望ましい順序を強制することは可能です。ただし、一般的に、このような低レベルで詳細なコードを記述することは避けたいと考えています。物事を間違えたり、見つけにくい微妙なバグを引き起こしたりするのは簡単すぎます。マルチスレッド コードを扱うときは、可能であれば常に高レベルのビルディング ブロックを使用するようにしてください。