Java Thread クラス
Thread クラスは、Java でスレッドを作成および管理するための中核クラスです。
Java では、各スレッドは Thread クラスのインスタンスです。スレッドは、プログラム内で独立して実行される「サブタスク」と理解でき、プログラムが複数の操作を同時に実行できるようにします。
Java のスレッドには、2 つの作成方法があります:
- Thread クラスを継承する
- Runnable インターフェースを実装する
Thread クラスの基本用法
スレッドの作成
例
// 方法1:Thread クラスを継承
class MyThread extends Thread {
public void run() {
System.out.println("スレッドが実行中です");
}
}
// 方法2:Runnable インターフェースを実装
class MyRunnable implements Runnable {
public void run() {
System.out.println("スレッドが実行中です");
}
}
public class Main {
public static void main(String[] args) {
// 継承方式を使用
MyThread thread1 = new MyThread();
thread1.start();
// インターフェース方式を使用
Thread thread2 = new Thread(new MyRunnable());
thread2.start();
}
}
class MyThread extends Thread {
public void run() {
System.out.println("スレッドが実行中です");
}
}
// 方法2:Runnable インターフェースを実装
class MyRunnable implements Runnable {
public void run() {
System.out.println("スレッドが実行中です");
}
}
public class Main {
public static void main(String[] args) {
// 継承方式を使用
MyThread thread1 = new MyThread();
thread1.start();
// インターフェース方式を使用
Thread thread2 = new Thread(new MyRunnable());
thread2.start();
}
}
スレッドのライフサイクル
Java のスレッドには以下の状態があります:
- NEW:新しく作成されたスレッドで、start() メソッドがまだ呼び出されていない状態
- RUNNABLE:実行可能な状態で、実行中または CPU 時間を待機している可能性がある状態
- BLOCKED:スレッドがブロックされ、モニターロックの取得を待機している状態
- WAITING:待機状態で、他のスレッドが特定の操作を実行するのを待機している状態
- TIMED_WAITING:有限時間の待機状態
- TERMINATED:スレッドが終了した状態
Thread クラスのよく使われるメソッド
基本制御メソッド
例
Thread thread = new Thread(() -> {
System.out.println("スレッド実行中");
});
thread.start(); // スレッドを起動
thread.join(); // スレッドの終了を待機
thread.sleep(1000); // スレッドを1秒間スリープ
System.out.println("スレッド実行中");
});
thread.start(); // スレッドを起動
thread.join(); // スレッドの終了を待機
thread.sleep(1000); // スレッドを1秒間スリープ
スレッドの優先順位
例
thread.setPriority(Thread.MAX_PRIORITY); // 最高優先順位(10)
thread.setPriority(Thread.NORM_PRIORITY); // デフォルトの優先順位(5)
thread.setPriority(Thread.MIN_PRIORITY); // 最低優先順位(1)
thread.setPriority(Thread.NORM_PRIORITY); // デフォルトの優先順位(5)
thread.setPriority(Thread.MIN_PRIORITY); // 最低優先順位(1)
スレッドの割り込み
例
thread.interrupt(); // スレッドを中断
// スレッド内で割り込み状態を確認
if (Thread.interrupted()) {
// 割り込み処理のロジック
}
// スレッド内で割り込み状態を確認
if (Thread.interrupted()) {
// 割り込み処理のロジック
}
スレッド同期
複数のスレッドが共有リソースにアクセスする場合、データの不整合を防ぐために同期メカニズムを使用する必要があります。
synchronized キーワードの使用
例
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
}
private int count = 0;
public synchronized void increment() {
count++;
}
}
Lock インターフェースの使用
例
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
スレッドプールと Thread クラス
実際の開発では、Thread オブジェクトを直接作成するのではなく、通常スレッドプールを使用してスレッドを管理します。
例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
System.out.println("スレッドがタスクを実行中");
});
}
executor.shutdown();
}
}
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
System.out.println("スレッドがタスクを実行中");
});
}
executor.shutdown();
}
}
ベストプラクティス
- Runnable インターフェースを実装する方法でスレッドを作成することを優先する
- スレッドプールを使用してスレッドリソースを管理する
- 過度な同期を避け、必要な場合にのみ同期メカニズムを使用する
- volatile キーワードを使用して変数の可視性を保証する
- Java 並行パッケージ(java.util.concurrent)の高度なツールクラスの使用を検討する
Thread クラスと関連する並行ツールを適切に使用することで、効率的で信頼性の高いマルチスレッド Java プログラムを作成できます。
その他の拡張