web-dev-qa-db-ja.com

Thread start()とRunnable run()の違いは何ですか

これら2つのRunnablesがあるとします。

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();
}
204
Ori Popowski

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

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

r1r2は、Runnableインターフェースを実装し、したがってrun()メソッドを実装するクラスの2つの異なるオブジェクトです。 r1.run()を呼び出すと、現在のスレッドでそれを実行していることになります。

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

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

t1t2は、クラスのオブジェクト Thread です。 t1.start()を呼び出すと、新しいスレッドを開始し、その新しいスレッド内でそれを実行するためにr1run()メソッドを内部的に呼び出します。

290
Bhesh Gurung

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

89
Mike Daniels

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

63
user207421

differenceは、プログラムがstart()メソッドを呼び出すと、newスレッドが作成され、run()内のコードが実行されることを意味します。newthread run()メソッドを直接呼び出すと、no新しいthreadは作成されず、run()内のコードが実行されます。現在のスレッドを直接.

Javaスレッドでのstart()run()の間の別の違いは、start()を2回呼び出すことはできないということです。一度開始されると、2番目のstart()メソッドはJavaではIllegalStateExceptionをスローしますが、run()メソッドはordinaryメソッドであるため、複数回呼び出すことができます。

30
Jaimin Patel

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

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

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

あなたがThread.run()を使っているのなら、あなたはマルチスレッドの機能をまったく使っていません。

22
aditya

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

8
Narendra Jaggi

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

start()メソッドは新しいスレッドを作成し、そのためにrun()メソッドを実行する必要があります。

6
Rohith

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

5
CHANDRAHAS

これらの答えのほとんどは全体像を見逃しています。それは、Java言語に関する限り、t.start()r.run()の間に他の2つの方法の間に違いがないということです。

どちらも単なる方法です。両方ともそれらを呼び出したスレッド内でを実行します。彼らは両方とも彼らがするためにコード化されたことは何でもし、そしてそれから彼らは両方とも、同じスレッドの中で、彼らの呼び出し側に戻る。

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

それで、t.start()は何をするのでしょうか?

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

そしてr.run()は何をするのですか?

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


t.start()は、新しいスレッドが欲しいときにあなたのコードが呼び出すためにライブラリが提供するメソッドです。

r.run()あなたライブラリを呼び出してin新しいスレッドを提供するメソッドです。

4
Solomon Slow

メンバーが作ったことは大丈夫ですので、何かを追加したいだけです。つまり、Javaは多重継承をサポートしていません。しかし、別のクラスAからクラスBを派生させたいが、1つのクラスからしか派生できない場合はどうなりますか。今の問題は、AとThreadの両方のクラスからどのように「派生」するかです。したがって、Runnable Interfaceを使うことができます。

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

public class B extends A implements Runnable{...
3
pommoisel

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

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

start()メソッドのソースコードを Thread class でご覧ください。

 /**
     * 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はこのネイティブメソッドを実行します。

2
Ravindra babu

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

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

start()はいつかrun()を呼び出すでしょう!

1
Gevorg