Java スレッド例

Javaスレッドの例へようこそ。プロセスとスレッドは2つの基本的な実行単位です。並行プログラミングは、Javaスレッドにより関心が深まります。

プロセス

A process is a self contained execution environment and it can be seen as a program or application. However a program itself contains multiple processes inside it. Java runtime environment runs as a single process which contains different classes and programs as processes.

スレッド

スレッドは「軽量プロセス」とも呼ばれます。スレッドは作成により少ないリソースを必要とし、プロセス内に存在し、プロセスのリソースを共有します。

Javaスレッドの例

すべてのJavaアプリケーションには少なくとも1つのスレッド、メインスレッドがあります。メモリ管理、システム管理、シグナル処理など、バックグラウンドで実行される他の多くのJavaスレッドが存在しますが、アプリケーションの観点から見れば、メインが最初のJavaスレッドであり、そこから複数のスレッドを作成できます。マルチスレッディングは、1つのプログラムで2つ以上のスレッドが同時に実行されることを指します。コンピュータのシングルコアプロセッサは同時に1つのスレッドしか実行できず、タイムスライシングはプロセスとスレッド間でプロセッサ時間を共有するOSの機能です。

Javaスレッドの利点

  1. Javaスレッドはプロセスと比較して軽量であり、スレッドを作成するのに少ない時間とリソースがかかります。
  2. スレッドは親プロセスのデータとコードを共有します
  3. スレッド間のコンテキスト切り替えは通常、プロセス間よりも負担が少ないです。
  4. スレッド間の通信はプロセス間の通信よりも相対的に簡単です。

Javaはプログラムでスレッドを作成するための2つの方法を提供しています。

  1. java.lang.Runnableインターフェースを実装する。
  2. java.lang.Threadクラスを拡張する。

Javaスレッドの例 – Runnableインターフェースの実装

クラスを実行可能にするには、java.lang.Runnableインターフェースを実装し、public void run()メソッドで実装を提供することができます。このクラスをスレッドとして使用するには、この実行可能クラスのオブジェクトを渡してスレッドオブジェクトを作成し、start()メソッドを呼び出して別のスレッドでrun()メソッドを実行する必要があります。ここでは、Runnableインターフェースを実装してJavaスレッドの例を示します。

package com.journaldev.threads;

public class HeavyWorkRunnable implements Runnable {

    @Override
    public void run() {
        System.out.println("Doing heavy processing - START "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            //データベース接続を取得し、DBから未使用のデータを削除する
            doDBProcessing();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Doing heavy processing - END "+Thread.currentThread().getName());
    }

    private void doDBProcessing() throws InterruptedException {
        Thread.sleep(5000);
    }

}

Javaスレッドの例 – Threadクラスの拡張

独自のJavaスレッドクラスを作成するには、java.lang.Threadクラスを拡張し、run()メソッドをオーバーライドすることができます。その後、そのオブジェクトを作成し、start()メソッドを呼び出して独自のJavaスレッドクラスの実行メソッドを実行できます。ここでは、Threadクラスを拡張する方法を示す単純なJavaスレッドの例を示します。

package com.journaldev.threads;

public class MyThread extends Thread {

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println("MyThread - START "+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
            //データベース接続を取得し、DBから未使用のデータを削除する
            doDBProcessing();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("MyThread - END "+Thread.currentThread().getName());
    }

    private void doDBProcessing() throws InterruptedException {
        Thread.sleep(5000);
    }
    
}

以下は、Javaスレッドを作成して実行する方法を示すテストプログラムです。

package com.journaldev.threads;

public class ThreadRunExample {

    public static void main(String[] args){
        Thread t1 = new Thread(new HeavyWorkRunnable(), "t1");
        Thread t2 = new Thread(new HeavyWorkRunnable(), "t2");
        System.out.println("Starting Runnable threads");
        t1.start();
        t2.start();
        System.out.println("Runnable Threads has been started");
        Thread t3 = new MyThread("t3");
        Thread t4 = new MyThread("t4");
        System.out.println("Starting MyThreads");
        t3.start();
        t4.start();
        System.out.println("MyThreads has been started");
        
    }
}

上記のJavaスレッドの例プログラムの出力は:

Starting Runnable threads
Runnable Threads has been started
Doing heavy processing - START t1
Doing heavy processing - START t2
Starting MyThreads
MyThread - START Thread-0
MyThreads has been started
MyThread - START Thread-1
Doing heavy processing - END t2
MyThread - END Thread-1
MyThread - END Thread-0
Doing heavy processing - END t1

いったんスレッドを開始すると、その実行はOSのタイムスライシングの実装に依存し、実行を制御することはできません。ただし、スレッドの優先順位を設定することはできますが、それでも高い優先度のスレッドが最初に実行されることを保証するものではありません。上記のプログラムを複数回実行すると、スレッドの開始と終了にはパターンがないことがわかります。

Runnable vs Thread

クラスがスレッドとして動作するだけでなく、他の機能も提供する場合は、Runnableインターフェースを実装してスレッドとして実行する方法を提供するべきです。クラスの目的がスレッドとして実行することだけである場合は、Threadクラスを拡張することができます。Runnableを実装することが推奨されます。なぜなら、Javaは複数のインターフェースの実装をサポートしているからです。Threadクラスを拡張すると、他のクラスを拡張することはできません。ヒント:スレッドが値を返さないことに気付いたかもしれませんが、スレッドが処理を行い、その結果をクライアントプログラムに返す必要がある場合は、Java Callable Futureを確認してください。更新:Java 8以降、Runnableは機能的インターフェースとなり、無名クラスを使用する代わりにラムダ式を使用してその実装を提供できます。詳細については、Java 8 Functional Interfacesをご覧ください。

Source:
https://www.digitalocean.com/community/tutorials/java-thread-example