JavaのThreadLocalの例を示します。

JavaのThreadLocalは、スレッド固有の変数を作成するために使用されます。オブジェクトのすべてのスレッドがその変数を共有するため、変数はスレッドセーフではありません。スレッドセーフを実現するには同期化を使用できますが、同期化を避けたい場合はThreadLocal変数を使用することができます。

JavaのThreadLocal

すべてのスレッドには、それぞれ独自のThreadLocal変数があり、get()メソッドやset()メソッドを使用してデフォルト値を取得したり、スレッド内で値を変更することができます。通常、ThreadLocalインスタンスは、スレッドに関連付けたい状態を持つクラスのプライベートな静的フィールドとして定義されます。

JavaのThreadLocalの例

(The wording may vary slightly depending on the context, but this conveys the same meaning.)

JavaプログラムにおけるThreadLocalの使用例を示し、各スレッドが独自のThreadLocal変数のコピーを持っていることを証明する小さな例をここに示します。ThreadLocalExample.java

package com.scdev.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
    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 pattern is changed here by thread, but it won't reflect to other threads
        formatter.set(new SimpleDateFormat());
        
        System.out.println("Thread Name= "+Thread.currentThread().getName()+" formatter = "+formatter.get().toPattern());
    }

}

上記のJava ThreadLocalの例プログラムの出力は、次のとおりです。

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

以下は、出力からわかるように、スレッド0はフォーマッタの値を変更しましたが、スレッド2のデフォルトのフォーマッタは初期値と同じままです。他のスレッドについても同じパターンが見られます。更新:Java 8では、ThreadLocalクラスが新しいメソッドwithInitial()で拡張され、Supplier関数インターフェースを引数にとるようになりました。したがって、ラムダ式を使用して簡単にThreadLocalインスタンスを作成することができます。例えば、上記のフォーマッタThreadLocal変数は以下のように1行で定義することができます。

private static final ThreadLocal<SimpleDateFormat> formatter = 
	ThreadLocal.<SimpleDateFormat>withInitial
	(() -> {return new SimpleDateFormat("yyyyMMdd HHmm");});

Java 8の機能に初めて触れる方は、「Java 8の機能」と「Java 8の関数型インターフェース」をチェックしてください。これでjavaプログラミングにおけるThreadLocalについては終わりです。参考資料:APIドキュメント

コメントを残す 0

Your email address will not be published. Required fields are marked *


广告
広告は10秒後に閉じます。
bannerAds