いつthread.run()
の代わりにJavaのthread.start()
を呼び出しますか?
特定の単体テストでrun()を呼び出して、並行性ではなく機能に厳密に関心がある場合があります。
決して。 run()を直接呼び出すと、通常のメソッド呼び出しと同じように(同じスレッドで)同期的にコードが実行されます。
Q:スレッドのstart()メソッドとrun()メソッドの違いは何ですか?
A:Threadクラスの別個のstart()およびrun()メソッドは、スレッド化されたプログラムを作成する2つの方法を提供します。 start()メソッドは、新しいスレッドの実行を開始し、run()メソッドを呼び出します。 start()メソッドはすぐに戻り、新しいスレッドは通常run()メソッドが戻るまで続きます。
Threadクラスのrun()メソッドは何もしないため、サブクラスはメソッドを2番目のスレッドで実行するコードでオーバーライドする必要があります。スレッドがRunnable引数でインスタンス化されている場合、スレッドのrun()メソッドは、代わりに新しいスレッドでRunnableオブジェクトのrun()メソッドを実行します。
スレッド化されたプログラムの性質に応じて、Thread run()メソッドを直接呼び出すと、start()メソッドを介して呼び出すのと同じ出力が得られますが、後者の場合、コードは実際に新しいスレッドで実行されます。
thread.run()
を実行しても、コードが実行される新しいThread
は作成されません。 thread.run()
コードの呼び出し元の現在のスレッドでコードを実行するだけです。
thread.start()
を実行すると、run()
メソッドが呼び出される新しいOSレベルのスレッドが作成されます。
本質的に:
シングルスレッドプログラミング→
run()
メソッドを直接呼び出す
マルチスレッドプログラミング→
start()
メソッドの呼び出し
さらに、他の人が述べたように、「テスト」はコードから直接run()
を呼び出すことができる唯一の推奨されるケースのようです。
これはすでに暗示されていますが、明確にするために、run()メソッドを呼び出すためだけに新しいThreadオブジェクトを作成することは、不必要に高価であり、大きな危険を伴うはずです。 Runnable implを作成し、(a)it's run()メソッドを目的の動作である場合は直接呼び出すか、(b)それで新しいスレッドを構築する方がはるかに優れた、より分離された設計になりますRunnableでスレッドを開始します。
さらに良いことに、さらにデカップリングするには、JDK 5以降のExecutor
インターフェイスとフレームワークをチェックしてください。これにより、簡単に言えば、タスク実行(Runnableインスタンス)をhow実行(現在のスレッドでRunnableを実行する可能性のあるExecutor実装、新しいスレッドで)から切り離すことができます。プールの既存のスレッド、その他)。
Threadクラスの個別のstart()
およびrun()
メソッドは、スレッド化プログラムを作成する2つの方法を提供します。 start()
メソッドは、新しいスレッドの実行を開始し、run()
メソッドを呼び出します。 start()
メソッドはすぐに戻り、新しいスレッドは通常run()
メソッドが戻るまで継続します。
Threadクラスのrun()
メソッドは何もしないので、サブクラスは2番目のスレッドで実行するコードでメソッドをオーバーライドする必要があります。スレッドがRunnable引数でインスタンス化されている場合、スレッドのrun()
メソッドは、代わりに新しいスレッドのRunnableオブジェクトのrun()
メソッドを実行します.
スレッド化されたプログラムの性質によっては、Thread run()
メソッドを直接呼び出すと、start()
メソッドを介して呼び出すのと同じ出力が得られますが、後者の場合、コードは実際に実行されます新しいスレッド。
thread.start()
を呼び出すと、次にthread.run()
を呼び出します。 thread.start()
をバイパスして直接thread.run()
に移動する場合を考えることはできません
質問が「なぜrunメソッドの代わりにスレッド開始メソッドが直接呼び出されるのか」だったら、以下のコード例で答えました。それが明確になることを願っています。以下の例では:
/*
By calling t1.start(),
we are getting the main calling thread returned immediately
after the t1.start() called and is ready to proceed for other
operations.And the thread t1 starts executing the run method of the object r.
Hence the the output will be:
I am the main thread , i created thread t1 and had it execute run method, which is currently looping from 0 to 1000000
I am done executing run method of testThread
*/
/* If we call t1.run() instead of t1.start(), (just replace t1.start() with t1.run() in the code for testing)
its like a regular method call and the main thread will not return until the run method completes,
hence the output will be:
I am done executing run method of testThread
I am the main thread , i created thread t1 and had it execute run method, which is currently looping for i to 1000000
*/
class testThread implements Runnable{
public void run()
{
for(int i=0;i<1000000;i++){} //a simple delay block to clarify.
System.out.println("I am done executing run method of testThread");
}
}
public class mainClass{
public static void main(String [] args)
{
testThread r = new testThread();
Thread t1 = new Thread(r);
t1.start(); /* Question is: can we call instead t1.run() */
System.out.println("I am the main thread , i created thread t1 and had it execute run method, which is currently looping for i to 1000000");
}
}
同期的に実行する場合。 runメソッドを呼び出しても、実際にはマルチスレッドは実行されません。 startメソッドは、runメソッドを呼び出す新しいスレッドを作成します。
他のメソッドと同じようにrun()の内容を実行する場合。もちろん、スレッドを開始しないでください。
同期メソッドと非同期メソッドの開始および実行メソッドの使用を知っていると仮定します。 runメソッドは、機能をテストするためだけに使用できます。
さらに、状況によっては、1つのrunメソッドと他のstartメソッドが呼び出される2つの異なるオブジェクトを持つことにより、同期と非同期の機能要件を持つ2つの異なる場所で同じスレッドクラスを使用できます。
上記のすばらしいコメントに注意してください。時には、「start」メソッドを使用して異なるスレッドを実行するマルチスレッドコードを作成する場合があります。デバッグに「開始」ではなく「実行」を使用すると、コードが同期して実行され、デバッグがはるかに簡単になるため、はるかに簡単になります。
少なくともJVM 1.6では、多少のチェックがあり、実行はネイティブに呼び出されます。
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
start0();
if (stopBeforeStart) {
stop0(throwableFromStop);
}
}
private native void start0();