Java Language
ThreadLocal
サーチ…
備考
呼び出しを呼び出す際に内部に依存するが、 SimpleDateFormat
、 Marshaller
ようにステートレスであるオブジェクトに最適
以下のためにRandom
にThreadLocalの使用状況、使用することを検討してくださいThreadLocalRandom
ThreadLocal Java 8の関数の初期化
public static class ThreadLocalExample
{
private static final ThreadLocal<SimpleDateFormat> format =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd_HHmm"));
public String formatDate(Date date)
{
return format.get().format(date);
}
}
基本的なThreadLocalの使用法
JavaのThreadLocal
は、スレッドのローカル変数を作成するために使用されます。 Objectのスレッドは変数を共有しているため、変数はスレッドセーフではありません。スレッドの安全性を確保するために同期を使用することができますが、同期を避けたい場合は、ThreadLocalを使用してスレッドのローカルな変数を作成できます。つまり、そのスレッドのみがその変数を読み書きできるため、それぞれの他のThreadLocal変数にアクセスすることはできません。
これは、 ThreadLocal
変数を使うために使うことができます。たとえば、Webサービスのようなスレッドプールがある状況では、たとえば、リクエストごとに毎回SimpleDateFormat
オブジェクトを作成するのは時間がかかり、 SimpleDateFormat
はスレッドセーフではないため、スタティックなものを作成できないため、毎回SimpleDateFormat
を作成するオーバーヘッドなしにスレッドセーフな操作を実行できるようにThreadLocalを作成できます時間。
以下のコードは、どのように使用できるかを示しています。
すべてのスレッドには独自のThreadLocal
変数があり、 get()
set()
メソッドとset()
メソッドを使用してデフォルト値を取得したり、Threadのローカル値を変更することができます。
ThreadLocal
インスタンスは、通常、状態をスレッドに関連付けるクラスのプライベート静的フィールドです。
ここでは、JavaプログラムでThreadLocalを使用し、すべてのスレッドにThreadLocal
変数の独自のコピーがあることを示す小さな例を示します。
package com.examples.threads;
import java.text.SimpleDateFormat;
import java.util.Random;
public class ThreadLocalExample implements Runnable{
// SimpleDateFormat is not thread-safe, so give one to each thread
// SimpleDateFormat is not thread-safe, so give one to each thread
private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
@Override
protected SimpleDateFormat initialValue()
{
return new SimpleDateFormat("yyyyMMdd HHmm");
}
};
public static void main(String[] args) throws InterruptedException {
ThreadLocalExample obj = new ThreadLocalExample();
for(int i=0 ; i<10; i++){
Thread t = new Thread(obj, ""+i);
Thread.sleep(new Random().nextInt(1000));
t.start();
}
}
@Override
public void run() {
System.out.println("Thread Name= "+Thread.currentThread().getName()+" default Formatter = "+formatter.get().toPattern());
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
formatter.set(new SimpleDateFormat());
System.out.println("Thread Name= "+Thread.currentThread().getName()+" formatter = "+formatter.get().toPattern());
}
}
出力:
Thread Name= 0 default Formatter = yyyyMMdd HHmm
Thread Name= 1 default Formatter = yyyyMMdd HHmm
Thread Name= 0 formatter = M/d/yy h:mm a
Thread Name= 2 default Formatter = yyyyMMdd HHmm
Thread Name= 1 formatter = M/d/yy h:mm a
Thread Name= 3 default Formatter = yyyyMMdd HHmm
Thread Name= 4 default Formatter = yyyyMMdd HHmm
Thread Name= 4 formatter = M/d/yy h:mm a
Thread Name= 5 default Formatter = yyyyMMdd HHmm
Thread Name= 2 formatter = M/d/yy h:mm a
Thread Name= 3 formatter = M/d/yy h:mm a
Thread Name= 6 default Formatter = yyyyMMdd HHmm
Thread Name= 5 formatter = M/d/yy h:mm a
Thread Name= 6 formatter = M/d/yy h:mm a
Thread Name= 7 default Formatter = yyyyMMdd HHmm
Thread Name= 8 default Formatter = yyyyMMdd HHmm
Thread Name= 8 formatter = M/d/yy h:mm a
Thread Name= 7 formatter = M/d/yy h:mm a
Thread Name= 9 default Formatter = yyyyMMdd HHmm
Thread Name= 9 formatter = M/d/yy h:mm a
出力から、Thread-0はフォーマッタの値を変更しましたが、まだスレッド2のデフォルトフォーマッタは初期化された値と同じであることがわかります。
1つの共有オブジェクトを持つ複数のスレッド
この例では、オブジェクトは1つしかありませんが、異なるスレッド間で共有/実行されています。状態を保存するためのフィールドの通常の使用は可能ではありません。なぜなら、他のスレッドもそれを見たり(おそらく見えないかもしれないからです)。
public class Test {
public static void main(String[] args) {
Foo foo = new Foo();
new Thread(foo, "Thread 1").start();
new Thread(foo, "Thread 2").start();
}
}
Fooではゼロから始まります。ステートをフィールドに保存する代わりに、静的にアクセス可能なThreadLocalオブジェクトに現在の番号を格納します。この例の同期は、ThreadLocalの使用とは関係なく、より良いコンソール出力を保証することに注意してください。
public class Foo implements Runnable {
private static final int ITERATIONS = 10;
private static final ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
@Override
public void run() {
for (int i = 0; i < ITERATIONS; i++) {
synchronized (threadLocal) {
//Although accessing a static field, we get our own (previously saved) value.
int value = threadLocal.get();
System.out.println(Thread.currentThread().getName() + ": " + value);
//Update our own variable
threadLocal.set(value + 1);
try {
threadLocal.notifyAll();
if (i < ITERATIONS - 1) {
threadLocal.wait();
}
} catch (InterruptedException ex) {
}
}
}
}
}
出力から、各スレッドはそれ自身のためにカウントされ、他のスレッドの値は使用されないことがわかります。
Thread 1: 0
Thread 2: 0
Thread 1: 1
Thread 2: 1
Thread 1: 2
Thread 2: 2
Thread 1: 3
Thread 2: 3
Thread 1: 4
Thread 2: 4
Thread 1: 5
Thread 2: 5
Thread 1: 6
Thread 2: 6
Thread 1: 7
Thread 2: 7
Thread 1: 8
Thread 2: 8
Thread 1: 9
Thread 2: 9