ホームページ Java &#&チュートリアル Java マルチスレッドでの ThreadLocal の使用

Java マルチスレッドでの ThreadLocal の使用

Oct 17, 2018 pm 04:21 PM
java マルチスレッド化

この記事の内容は、Java マルチスレッドでの ThreadLocal の使用に関するものです。必要な方は参考にしていただければ幸いです。

マルチスレッド環境では、synchronized メソッドを使用して HashMap# にアクセスするなど、非スレッドセーフ変数にアクセスするときにスレッド同期を実行する必要があります。 ## 実例。ただし、同期アクセスは同時実行性を低下させ、システムのパフォーマンスに影響を与えます。このとき、各スレッドに独立した変数を割り当てると、非スレッド セーフな変数を非同期的に使用できるようになり、そのような変数をスレッド ローカル変数と呼びます。

名前が示すように、スレッド ローカル変数は、各スレッドが変数の独自の独立したコピーを持ち、通常のローカル変数のように他のスレッドからアクセスできないことを意味します。

Java は言語レベルのスレッドローカル変数を提供していませんが、今回の主役である ThreadLocal クラスのクラスライブラリ内でスレッドローカル変数の機能を提供しています。

ThreadLocal の使用法

Java マルチスレッドでの ThreadLocal の使用
##ThreadLocal の Java8 バージョンには、上の図に示す 4 つがあります。 2 つのパブリック メソッドと 1 つの保護されたメソッドがあります。最初のメソッドは初期値 (デフォルトでは null) を返すために使用されます。 2 番目の静的メソッド withInitial(Supplier extends S>supplier) は Java8 バージョンで新しく追加されたもので、次の 3 つのインスタンス メソッドは非常に単純です。

Java8 より前では、ThreadLocal を使用するときに初期値を設定する場合は、ThreadLocal クラスを継承し、保護された T のinitialValue() メソッドをオーバーライドする必要があります。例:

ThreadLocal<integer> threadLocal = new ThreadLocal<integer>() {
    @Override
    protected Integer initialValue() {
        return 0;
    }
};</integer></integer>
ログイン後にコピー
##。 #Java8 版でも利用可能 新しく追加された静的メソッド withInitial(Supplier extends S>supplier) は、初期値を設定するのに非常に便利です。例えば:
ThreadLocal<integer> threadLocal = ThreadLocal.withInitial(() -> 0);

System.out.println(threadLocal.get());
threadLocal.set(16);
System.out.println(threadLocal.get());
threadLocal.remove();
System.out.println(threadLocal.get());

// 同一个线程的输出
0
16
0
Process finished with exit code 0</integer>
ログイン後にコピー

ThreadLocal の原理

では、ThreadLocal はスレッドローカル変数の機能をどのように実装するのでしょうか?実際、ThreadLocal の基本原理はそれほど複雑ではありません。 ThreadLocal は内部で静的クラス ThreadLocalMap を定義します。ThreadLocalMap のキーは ThreadLocal オブジェクトです。ただし、この ThreadLocalMap は ThreadLocal クラスに保持されます。 ThreadLocal のソース コードの一部を見てみましょう:

    // ThreadLocal的set方法
    public void set(T value) {
        // 获取当前线程对象
        Thread t = Thread.currentThread();
        // 获取Map
        ThreadLocalMap map = getMap(t);
        if (map != null)
            // 设置值
            map.set(this, value);
        else
            // 初始化Map
            createMap(t, value);
    }
    
    // ThreadLocal的createMap方法
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
    
    // Thread类定义的实例域
    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;
ログイン後にコピー
ThreadLocal のコア実装は ThreadLocalMap の実装であり、内部でデータを格納する Entry クラスを宣言していることがわかります:

static class Entry extends WeakReference<threadlocal>> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal> k, Object v) {
        super(k);
        value = v;
    }
}</threadlocal>
ログイン後にコピー
。 ThreadLocalMap の実装 HashMap の実装と類似点があります。たとえば、配列はデータの保存と自動展開にも使用されます。違いは、ハッシュ アルゴリズムとハッシュ衝突後の処理です。

        // ThreadLocalMap的set方法
        private void set(ThreadLocal> key, Object value) {

            Entry[] tab = table;
            int len = tab.length;
            // 计算在Entry[]中的索引,每个ThreadLocal对象都有一个hash值threadLocalHashCode,每初始化一个ThreadLocal对象,hash值就增加一个固定的大小0x61c88647
            int i = key.threadLocalHashCode & (len-1);

            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal> k = e.get();
                // 如果键已存在就更新值
                if (k == key) {
                    e.value = value;
                    return;
                }
                // 代替无效的键
                if (k == null) {
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }

            tab[i] = new Entry(key, value);
            int sz = ++size;
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }
        
        private static int nextIndex(int i, int len) {
            return ((i + 1 ThreadLocalMap が Entry[] 配列をリングとして扱っていることがわかります。計算したインデックスの位置を起点として、インデックスに既にデータがある場合はKeyが同じかどうかを判定し、同じであれば値を更新します。それ以外の場合は、空の位置が見つかるまで待って、そこに値を入れます。値を取得する場合も同様で、計算されたインデックスの位置から開始して、キーが同じであるかどうかを 1 つずつチェックします。ハッシュの衝突が多い場合、パフォーマンスがあまり良くない可能性があります。 <p></p><p>ThreadLocal のアプリケーション</p><p><strong></strong><code><br></code>##ThreadLocal のアプリケーションは非常に広範囲に渡ります。たとえば、Java エンジニアは次のようになります。 ThreadLocal は Spring フレームワークで非スレッドセーフのステートフル オブジェクトをカプセル化するために使用されるため、ほとんどの Bean をシングルトン スコープとして宣言できます。マルチスレッド コードを記述するときは、非スレッド セーフ ステートフル オブジェクトに同期的にアクセスする方が良いのか、それとも ThreadLocal を使用して非スレッド セーフ ステートフル オブジェクトをカプセル化する方が良いのかを考えることもできます。 </p><p><code><span style="font-family: 微软雅黑, Microsoft YaHei;"></span><br></code></p>
ログイン後にコピー

以上がJava マルチスレッドでの ThreadLocal の使用の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Java での日付までのタイムスタンプ Java での日付までのタイムスタンプ Aug 30, 2024 pm 04:28 PM

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

カプセルの量を見つけるためのJavaプログラム カプセルの量を見つけるためのJavaプログラム Feb 07, 2025 am 11:37 AM

カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4

未来を創る: まったくの初心者のための Java プログラミング 未来を創る: まったくの初心者のための Java プログラミング Oct 13, 2024 pm 01:32 PM

Java は、初心者と経験豊富な開発者の両方が学習できる人気のあるプログラミング言語です。このチュートリアルは基本的な概念から始まり、高度なトピックに進みます。 Java Development Kit をインストールしたら、簡単な「Hello, World!」プログラムを作成してプログラミングを練習できます。コードを理解したら、コマンド プロンプトを使用してプログラムをコンパイルして実行すると、コンソールに「Hello, World!」と出力されます。 Java の学習はプログラミングの旅の始まりであり、習熟が深まるにつれて、より複雑なアプリケーションを作成できるようになります。

See all articles