Java
 Computer >> コンピューター >  >> プログラミング >> Java

JavaでThread.start()の代わりにThread.run()を呼び出すのはどんなとき?違いを徹底解説


スレッドに対してstart()メソッドを呼び出すと、そのスレッドの実行が開始され、run()メソッドはJava仮想マシン(JVM)によって呼び出されます。一方、run()メソッドを直接呼び出した場合は、Threadクラス(またはRunnableインターフェース)の通常のオーバーライドメソッドとして扱われ、新しいスレッドではなく現在のスレッドのコンテキスト内で実行されるという重要な違いがあります。

start()とrun()の違い

start()メソッドrun()メソッド
新しいスレッドを作成し、そのスレッド上でrun()を実行する現在のスレッド上で通常のメソッドとして実行される
JVMによってスケジューリングされ、並行処理が可能呼び出し元のスレッドで同期的・直列に実行される
マルチスレッド処理を実現できる並列処理にはならず、マルチスレッドの意味がない

コード例

public class CallRunMethodTest extends Thread {
    @Override
    public void run() {
        System.out.println("In the run() method: " + Thread.currentThread().getName());
        for(int i = 0; i < 5 ; i++) {
            System.out.println("i: " + i);
            try {
                Thread.sleep(300);
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        CallRunMethodTest t1 = new CallRunMethodTest();
        CallRunMethodTest t2 = new CallRunMethodTest();
        t1.run(); // start()メソッドの代わりにrun()メソッドを直接呼び出し
        t2.run(); // start()メソッドの代わりにrun()メソッドを直接呼び出し
    }
}

上記の例では、2つのスレッドオブジェクトを作成していますが、start()メソッドを呼び出さずに、run()メソッドを直接呼び出しています。

実行結果

In the run() method: main
i: 0
i: 1
i: 2
i: 3
i: 4
In the run() method: main
i: 0
i: 1
i: 2
i: 3
i: 4

結果のポイント

注目すべきは、出力に表示されているスレッド名がすべて「main」になっている点です。これは、run()メソッドが新しいスレッドではなく、mainメソッドを実行しているメインスレッド上で順番に実行されたことを示しています。もしstart()メソッドを呼び出していれば、「Thread-0」「Thread-1」といった別々のスレッド名が表示され、2つのスレッドが並行して動作します。

run()を直接呼び出してもよいケース

マルチスレッド処理を行いたい場合は、必ずstart()メソッドを使用すべきです。ただし、次のような場面ではrun()を直接呼び出すことにも意味があります。

  • 単体テストなどで、スレッド生成のオーバーヘッドなしにrun()内部のロジックだけを検証したい場合
  • デバッグ時に、現在のスレッドのスタックトレースで挙動を追いたい場合
  • Runnableを単なる「処理のまとまり(タスク)」として扱い、スレッド管理を独自に行う設計の場合

つまり、run()を直接呼び出すことは「新しいスレッドを立ち上げない」ことを意味します。意図的にシングルスレッドで実行したい場合を除き、実際にスレッドを動かしたいときは必ずstart()メソッドを使うようにしましょう。

  1. Javaのpack()メソッドとは?使い方とsetSize()との違いを解説

    pack()メソッドは、JavaのWindowクラスで定義されているメソッドで、フレーム内のすべてのコンポーネントがそれぞれの推奨サイズ(preferred size)以上で表示されるように、ウィンドウのサイズを自動的に調整します。 代替手段として、setSize()メソッドやsetBounds()メソッドを呼び出して、フレームのサイズを明示的に指定する方法もあります。しかし一般的には、pack()メソッドを使用する方がsetSize()よりも推奨されています。その理由は、pack()がフレームのサイズ決定をレイアウトマネージャーに委ねることができ、レイアウトマネージャーはプラットフォーム間の

  2. JavaのSwingUtilities.invokeLater()メソッドの使い方を徹底解説

    invokeLater()メソッドとはinvokeLater()メソッドは、SwingUtilitiesクラスが提供するstaticメソッドの一つで、AWTイベントディスパッチスレッド(Event Dispatch Thread)上でタスクを非同期に実行するために使用されます。このメソッドはSwingUtilities.invokeAndWait()とよく似た動作をしますが、大きな違いは、処理のリクエストをイベントキューに登録した後、すぐに呼び出し元へ制御を返すという点です。つまり、invokeLater()は引数で渡されたRunnableオブジェクト内のコードブロックの実行完了を待ちません。