Javaにおけるスレッドの状態と制御方法

スレッドのライフサイクルと操作

1. スレッドの安全な停止

JDKが提供するstop()destroy()は非推奨です。代わりに、フラグ変数による協調的終了を実装します。

public class GracefulShutdown implements Runnable {
    private volatile boolean active = true;

    @Override
    public void run() {
        int counter = 0;
        while (active) {
            System.out.println("Task running: " + counter++);
        }
    }

    public void requestStop() {
        this.active = false;
    }

    public static void main(String[] args) {
        GracefulShutdown task = new GracefulShutdown();
        Thread worker = new Thread(task);
        worker.start();

        for (int i = 0; i < 100; i++) {
            if (i == 75) {
                task.requestStop();
                System.out.println("Shutdown requested...");
            }
            System.out.println("Main thread: " + i);
        }
    }
}

2. スレッドの一時停止(Sleep)

Thread.sleep()は指定ミリ秒間スレッドを待機させますが、ロックは保持したままです。時間経過後、Runnable状態に戻ります。

import java.text.SimpleDateFormat;
import java.util.Date;

public class ClockTicker {
    public static void main(String[] args) {
        while (true) {
            try {
                Thread.sleep(1000);
                String now = new SimpleDateFormat("HH:mm:ss").format(new Date());
                System.out.println("Current time: " + now);
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
                break;
            }
        }
    }
}

3. スレッドの礼譲(Yield)

Thread.yield()は現在のスレッドを一時的にRunnable状態に戻し、他のスレッドに実行機会を与えます。ただし、スケジューラ次第で同じスレッドが再選択される可能性があります。

public class CooperativeYield implements Runnable {
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + ": starting");
        Thread.yield();
        System.out.println(name + ": resumed after yield");
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new CooperativeYield(), "Worker-A");
        Thread t2 = new Thread(new CooperativeYield(), "Worker-B");
        t1.start(); t2.start();
    }
}

4. スレッドの結合(Join)

join()は呼び出し元スレッドをブロックし、対象スレッドの終了を待ちます。これにより並列処理を直列化できます。

public class SequentialExecution implements Runnable {
    @Override
    public void run() {
        for (int step = 1; step <= 5; step++) {
            System.out.println("Subtask #" + step);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread background = new Thread(new SequentialExecution());
        background.start();

        for (int i = 1; i <= 10; i++) {
            if (i == 3) {
                System.out.println("Waiting for background task...");
                background.join();
            }
            System.out.println("Main step: " + i);
        }
    }
}

5. スレッド状態の監視

JavaではThread.getState()で以下の6状態を取得可能です:

  • NEW:生成済みだが未開始
  • RUNNABLE:実行可能または実行中
  • BLOCKED:ロック待ち
  • WAITING:無期限待機中
  • TIMED_WAITING:時間制限付き待機中
  • TERMINATED:終了済み
public class StateMonitor implements Runnable {
    @Override
    public void run() {
        try { Thread.sleep(3000); } 
        catch (InterruptedException e) { Thread.currentThread().interrupt(); }
    }

    public static void main(String[] args) {
        Thread monitor = new Thread(new StateMonitor());
        
        System.out.println("Initial: " + monitor.getState());
        monitor.start();
        System.out.println("After start: " + monitor.getState());

        while (monitor.isAlive()) {
            try { Thread.sleep(500); } 
            catch (InterruptedException e) { break; }
            System.out.println("Current: " + monitor.getState());
        }
        System.out.println("Final: " + monitor.getState());
    }
}

タグ: Java Thread synchronization Multithreading concurrency

5月27日 12:09 投稿