広告

Java : ThreadLocal - API使用例

ThreadLocal (Java SE 21 & JDK 21) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様書のおともにどうぞ。


概要

このクラスはスレッド・ローカル変数を提供します。 これらの変数は、getメソッドまたはsetメソッドを使ってアクセスするスレッドがそれぞれ独自に、変数の初期化されたコピーを持つという点で、通常の変数と異なります。

クラス構成

ThreadLocal クラスは、変数を各スレッドに紐づけて管理します。
そのため、ThreadLocal 自体のインスタンスは複数のスレッドで共有でき、かつ、スレッドごとに独立した変数を get/set できます。

class SharedTask implements Runnable {
    private final ThreadLocal<Integer> local = ThreadLocal.withInitial(() -> 0);

    @Override
    public void run() {
        try {
            final var count = local.get() + 1;
            final var id = Thread.currentThread().threadId();

            System.out.printf("thread id = %d : count = %d%n", id, count);

            TimeUnit.MILLISECONDS.sleep(100);
            local.set(count);

        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        }
    }
}

try (final var executor = Executors.newFixedThreadPool(3)) {

    final var sharedTask = new SharedTask();
    for (int i = 0; i < 9; i++) {
        executor.submit(sharedTask);
    }
}

// 結果
// ↓
//thread id = 32 : count = 1
//thread id = 33 : count = 1
//thread id = 34 : count = 1
//thread id = 32 : count = 2
//thread id = 33 : count = 2
//thread id = 34 : count = 2
//thread id = 32 : count = 3
//thread id = 33 : count = 3
//thread id = 34 : count = 3

コンストラクタ

ThreadLocal ()

スレッド・ローカル変数を作成します。

final var local = new ThreadLocal<String>();
System.out.println(local.get()); // null

local.set("abc");
System.out.println(local.get()); // abc
final var local = new ThreadLocal<Integer>();
System.out.println(local.get()); // null

local.set(123);
System.out.println(local.get()); // 123

メソッド

T get ()

このスレッド・ローカル変数の現行スレッドのコピー内の値を返します。

class SharedTask implements Runnable {
    private final ThreadLocal<Integer> local = ThreadLocal.withInitial(() -> 0);

    @Override
    public void run() {
        try {
            final var count = local.get() + 1;
            final var id = Thread.currentThread().threadId();

            System.out.printf("thread id = %d : count = %d%n", id, count);

            TimeUnit.MILLISECONDS.sleep(100);
            local.set(count);

        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        }
    }
}

try (final var executor = Executors.newFixedThreadPool(3)) {

    final var sharedTask = new SharedTask();
    for (int i = 0; i < 9; i++) {
        executor.submit(sharedTask);
    }
}

// 結果
// ↓
//thread id = 32 : count = 1
//thread id = 33 : count = 1
//thread id = 34 : count = 1
//thread id = 32 : count = 2
//thread id = 33 : count = 2
//thread id = 34 : count = 2
//thread id = 32 : count = 3
//thread id = 33 : count = 3
//thread id = 34 : count = 3

protected T initialValue ()

このスレッド・ローカル変数に対する現在のスレッドの「初期値」を返します。

関連 : withInitial(Supplier<? extends S> supplier)

final var local = new ThreadLocal<String>() {
    @Override
    protected String initialValue() {
        return "abc";
    }
};
System.out.println(local.get()); // abc

local.set("XYZ");
System.out.println(local.get()); // XYZ

void remove ()

このスレッド・ローカル変数に対する現在のスレッドの値を削除します。

final var local = ThreadLocal.withInitial(() -> "abc");
System.out.println(local.get()); // abc

local.set("XYZ");
System.out.println(local.get()); // XYZ

local.remove();
System.out.println(local.get()); // abc
final var local = new ThreadLocal<Integer>();
System.out.println(local.get()); // null

local.set(123);
System.out.println(local.get()); // 123

local.remove();
System.out.println(local.get()); // null

void set (T value)

このスレッド・ローカル変数の現在のスレッドのコピーを指定された値に設定します。

このメソッドの使用例は、get() にまとめて記載しました。
そちらのAPI使用例をご参照ください。

static <S> ThreadLocal<S> withInitial (Supplier<? extends S> supplier)

スレッド・ローカル変数を作成します。

final var local = ThreadLocal.withInitial(() -> "abc");
System.out.println(local.get()); // abc

local.set("XYZ");
System.out.println(local.get()); // XYZ

関連記事

ページの先頭へ