サーチ…


備考

呼び出しを呼び出す際に内部に依存するが、 SimpleDateFormatMarshallerようにステートレスであるオブジェクトに最適

以下のために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


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow