スレッドのstart()とRunnable run()の違いは何ですか


224

次の2つのRunnableがあるとします。

class R1 implements Runnable {
    public void run() {  }
    
}

class R2 implements Runnable {
    public void run() {  }
    
}

次に、これの違いは何ですか?

public static void main() {
    R1 r1 = new R1();
    R2 r2 = new R2();

    r1.run();
    r2.run();
}

この:

public static void main() {
    R1 r1 = new R1();
    R2 r2 = new R2();
    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);

    t1.start();
    t2.start();
}

回答:


309

最初の例:複数のスレッドはありません。どちらも単一の(既存の)スレッドで実行されます。スレッドは作成されません。

R1 r1 = new R1();
R2 r2 = new R2();

r1そしてr2実装するクラスのちょうど2つの異なるオブジェクトであるRunnableインターフェースを、従って実装run()方法。呼び出すr1.run()と、現在のスレッドで実行されます。

2番目の例: 2つの別々のスレッド。

Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);

t1およびt2クラスのオブジェクトですThread。を呼び出すとt1.start()、新しいスレッドが開始され、内部でのrun()メソッドが呼び出されて、r1その新しいスレッド内で実行されます。


5
Thread#start()を呼び出す前に、OSスレッドに関連するものは何も起こらないと思いますか?これは単なるJavaオブジェクトです。
Jaskey 14

4
ドキュメントによると、それは正しいです。ドキュメントに準拠するスレッドオブジェクト初期化コードを確認します。また、ソースコードではstart()、それはnatvieメソッドを呼び出すです。
Bhesh Gurung、2015

3
スレッドコンストラクタドキュメントはこちらです。スレッドオブジェクト初期化ソースはこちらです。start()メソッドソースはこちらです。
Bhesh Gurung、2015

92

run()直接呼び出すだけの場合は、他のメソッド呼び出しと同じように、呼び出しスレッドで実行されます。Thread.start()ランナブルのrunメソッドが並列に実行されるように、実際に新しいスレッドを作成する必要があります。


2
Hotspot JVMでは、Javaスレッドとネイティブスレッドの間に直接マッピングがあります。Thread.start()呼び出しにより、スレッドの状態が新しい状態からRunnable状態に移行します。実行可能とは、スレッドが実行中であることを意味しません。ネイティブスレッドが初期化されると、ネイティブスレッドはrun()Javaスレッドのメソッドを呼び出し、スレッドの状態をRunnableからRunningに変更します。スレッドが終了すると、ネイティブスレッドとJavaスレッドの両方のすべてのリソースが解放されます。
オーバーエクスチェンジ'27

@overexchange状態の変化に関する資料はどこにありますか。
twlkyao 2018

73

違いは、現在のスレッドでメソッドを呼び出すだけでThread.start()run()メソッドを呼び出すスレッドを開始することです。Runnable.run()run()


35

違いは、プログラムが呼び出すときということであるstart()方法を、新しいスレッドが作成され、コードの内部がrun()で実行されていない新しいお電話の場合は一方で、スレッドrun()メソッドを直接新しいスレッドが作成され、コードの内部がrun()直接、現在のスレッドで実行されます。

とJavaスレッドのもう1つの違いstart()、2回呼び出すrun()ことができないことですstart()。開始すると、2番目のstart()呼び出しはIllegalStateExceptionJavaでスローされますがrun()、メソッドは通常のメソッドであるため、何度も呼び出すことができます。


21

実際にThread.start()新しいスレッドを作成し、独自の実行シナリオがあります。

Thread.start()run()メソッドを非同期的に呼び出し、新しいスレッドの状態をRunnableに変更します。

ただしThread.run()、新しいスレッドは作成されません。代わりに、現在実行中のスレッドでrunメソッドを同期的に実行します。

使用している場合Thread.run()は、マルチスレッドの機能をまったく使用していません。


8

invoke run()は、他のメソッド呼び出しと同様に、呼び出しスレッドで実行されています。一方 Thread.start()、新しいスレッドを作成します。呼び出しrun()はプログラム上のバグです。


7

run()mainメソッドで実行すると、mainメソッドrunのスレッドが、実行する必要があるスレッドの代わりにメソッドを呼び出します。

start()この方法は、新しいスレッドを作成し、そのためrun()の方法を行う必要があります


「メインメソッド」はそれとは何の関係もありません。
ローンの侯爵2013年

3
@EJP、mainライターによると、呼び出しメソッドを意味しました。彼の答えはかなり良いです。+1 ;-)
dom_beau 14年

1
@dom_beauそれが彼がそういう意味だったら彼はそう言ったはずだった。彼の言ったことは正しくなかった。この答えについては、「まったく良い」ものは何もありません。それは混乱した混乱です。
ローン侯爵

5

t.start() 新しいスレッドが必要なときにコードが呼び出すようにライブラリが提供するメソッドです。

r.run()方法であり、あなたがのために提供し、ライブラリを呼び出すため新しいスレッド。


これらの答えのほとんどは限りJava言語に関しては、間には多くの違いがあり、それである全体像、欠場t.start()r.run()任意の他の2つの方法の間であってよりを。

どちらも単なる方法です。どちらも、呼び出し元のスレッドで実行されます。彼らは両方とも、コード化されていることをすべて実行し、その後、同じスレッドで呼び出し元に戻ります。

最大の違いは、ほとんどのコードt.start()ネイティブコードであるのに対し、ほとんどの場合、コードr.run()は純粋なJavaになるということです。しかし、それは大した違いではありません。コードはコードです。ネイティブコードは見つけるのが難しく、見つけたときに理解するのも困難ですが、それでもコンピューターに何をすべきかを指示するのは単なるコードです。

それで、何をしt.start()ますか?

新しいネイティブスレッドを作成し、そのスレッドがを呼び出すように調整してt.run()から、新しいスレッドを実行するようにOSに指示します。その後、戻ります。

そして、何をしr.run()ますか?

面白いことに、この質問をする人はそれ書いた人です。 あなた(つまり、それを書いた開発者)が設計したことをr.run()すべて実行します。


4

Thread.start()コードはスレッドをスケジューラに登録し、スケジューラはrun()メソッドを呼び出します。また、ThreadRunnableインターフェイスですが、はクラスです。


3

メンバーが作ったポイントは大丈夫なので、何か追加したいだけです。重要なのは、JAVAはマルチ継承をサポートしないということです。しかし、クラスBを別のクラスAから派生させたいが、1つのクラスからしか派生できない場合はどうなりますか。ここでの問題は、AとThreadの両方のクラスから「派生」する方法です。したがって、Runnableインターフェイスを使用できます。

public class ThreadTest{
   public void method(){
      Thread myThread = new Thread(new B());
      myThread.start;
   }
}

public class B extends A implements Runnable{...

Runnableをおよそ一例の助けを借りて、うまく実行の説明()メソッド-インタフェースとスレッド-クラス
ピンキーWalve

1

run()メソッドを直接呼び出す場合、run()メソッドは呼び出し側スレッドの一部として実行されるため、マルチスレッド機能を使用していません。

start()スレッドでメソッドを呼び出すと、Java仮想マシンがrun()メソッドを呼び出し、2つのスレッドが同時に実行さmain()れます。現在のスレッド(例では)とその他のスレッド(r1例ではRunnable )です。

スレッドクラスstart()メソッドのソースコードを見てください

 /**
     * Causes this thread to begin execution; the Java Virtual Machine
     * calls the <code>run</code> method of this thread.
     * <p>
     * The result is that two threads are running concurrently: the
     * current thread (which returns from the call to the
     * <code>start</code> method) and the other thread (which executes its
     * <code>run</code> method).
     * <p>
     * It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.
     *
     * @exception  IllegalThreadStateException  if the thread was already
     *               started.
     * @see        #run()
     * @see        #stop()
     */
    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();

上記のコードでは、run()メソッドの呼び出しを確認できません。

private native void start0()run()メソッドの呼び出しを担当します。JVMはこのネイティブメソッドを実行します。


0

最初のケースrun()では、r1およびr2オブジェクトのメソッドを呼び出すだけです。

2番目のケースでは、実際には2つの新しいスレッドを作成しています。

start()いつか電話run()します!


7
実際、start()はrun()を呼び出しません。呼び出した場合、run()メソッドは、start()を呼び出したのと同じスレッドによって実行されます。start()は、run()メソッドを呼び出すスレッドを作成します。
Bruno Reis

0

runメソッド: -Runnableインターフェースで最初に作成され、ThreadクラスとThreadサブクラス(ThreadがそのソースコードでRunnableを実装するため)およびRunnableインターフェースの他の実装クラスでオーバーライドされる抽象メソッドです。-スレッド(実行可能オブジェクト)に意図したタスクをロードするために使用されるため、オーバーライドしてそのタスクを書き込みます。

startメソッド: -Threadクラスで定義されています。スレッドオブジェクトでstartメソッドが呼び出されると、 1-内部でstart0()と呼ばれるネイティブ(nonjava)メソッドが呼び出されます。方法。

start0(); メソッド: 低処理(スレッドのスタック作成とプロセッサキューでのスレッドの割り当て)を担当します。この時点で、スレッドは準備完了/実行可能状態にあります。

2-スレッドスケジューラが、スレッドがプロセッサコアに入ると判断した時点で(スレッドの優先順位とOSスケジューリングアルゴリズム)、runnableオブジェクトでrunメソッドが呼び出されます(現在のRunnableスレッドオブジェクトか、渡されたRunnableオブジェクトかスレッドコンストラクターへ)、ここでスレッドはRunning状態に入り、タスクの実行を開始します(runメソッド)


-2

Threadクラスの個別のstart()メソッドとrun()メソッドは、スレッド化されたプログラムを作成する2つの方法を提供します。start()メソッドは、新しいスレッドの実行を開始し、run()メソッドを呼び出します。start()メソッドはすぐに戻り、新しいスレッドは通常、run()メソッドが戻るまで続きます。

Threadクラスのrun()メソッドは何もしないので、サブクラスは2番目のスレッドで実行するコードでメソッドをオーバーライドする必要があります。スレッドがRunnable引数でインスタンス化されている場合、スレッドのrun()メソッドは、代わりに新しいスレッドでRunnableオブジェクトのrun()メソッドを実行します。

スレッド化されたプログラムの性質によっては、スレッドのrun()メソッドを直接呼び出すと、start()メソッドを介して呼び出すのと同じ出力が得られますが、後者の場合、コードは実際には新しいスレッドで実行されます。


2
`run() 'の呼び出しは、スレッド化されたプログラムを作成する方法ではありません。方法は1つだけです。
ローンの侯爵

-2

Start()メソッドは、Thread拡張クラスのRunオーバーライドメソッドを呼び出し、Runnableはインターフェイスを実装します。

しかし、run()を呼び出すことでrunメソッドを検索しますが、Runnableインターフェースを実装するクラスの場合は、Runnableのrun()オーバーライドメソッドを呼び出します。

例:

`

public class Main1
{
A a=new A();
B b=new B();
a.run();//This call run() of Thread because run() of Thread only call when class 
        //implements with Runnable not when class extends Thread.
b.run();//This not run anything because no run method found in class B but it 
        //didn't show any error.

a.start();//this call run() of Thread
b.start();//this call run() of Thread
}

class A implements Runnable{
@Override
    public void run() {
            System.out.println("A ");
    }
}

class B extends Thread {

    @Override
    public void run() {
            System.out.println("B ");
    }
}

`

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.