2

クラスjava.lang.ThreadLocalに関するjavadocは、私を混乱させています。彼らは、スレッドローカル変数にアクセスする各スレッドには、独自に初期化された変数のコピーがあると言っています。これは、スレッドローカル変数に保持されている変数が多くのスレッドで共有される可能性があることを証明する例(実際の例ではありません)です。

package com.mohamad.test.threadlocal;

import java.util.List;

public class ThreadLocalExample {

    private static final ThreadLocal<List<Integer>> myThreadLocal = new ThreadLocal<List<Integer>>();

    public static List<Integer> get() {
        return (myThreadLocal.get());
    }

    public static void set(List<Integer> value) {
        myThreadLocal.set(value);
    }
}


package com.mohamad.test.threadlocal;

import java.util.ArrayList;
import java.util.List;


public class TestThreadLocal implements Runnable {

    private static List<Integer> MY_TEST_LIST = new ArrayList<Integer>(){
        /** The serialVersionUID */
        private static final long serialVersionUID = -2419885728976816054L;
        {add(1);}
    };


    /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    public void run() {
        ThreadLocalExample.set(MY_TEST_LIST);
        List<Integer> integers = ThreadLocalExample.get();
        integers.remove(0);
        System.out.println(Thread.currentThread().getName() + " finished successfully, The list's size is: "  + ThreadLocalExample.get().size() + "\n");
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        TestThreadLocal thread1 = new TestThreadLocal();
        Thread t1 = new Thread(thread1);
        t1.start();
        TestThreadLocal thread2 = new TestThreadLocal();
        Thread t2 = new Thread(thread2);
        t2.start();
    }
}

この例を実行すると、とによって共有されているjava.lang.IndexOutOfBoundsExceptionため、がスローされます。(そして、私たちが見たように、thread1とthread2が変数のsetメソッドを呼び出したのメソッドを呼び出したとき、それはの独立したローカルコピーを作成しませんでした)MY_TEST_LISTthread1thread2set(MY_TEST_LIST)ThreadLocalExampleThreadLocalMY_TEST_LIST

誰かがすでにこの質問をしている場合は、グーグルで調査しているときに面白いものが見つからなかったので、答えへのリンクを教えてください。

よろしく、

4

3 に答える 3

6

すべて順調。変数のホールドインThreadLocalはスレッドに対してローカルです。あなたの場合、それはローカルの参照であり、リスト自体ではありません。各スレッドには独自の参照のコピーがありますが、これらの参照はすべて同じ場所を指しています。言い換えると、各スレッドは異なる参照を保持できListますが、あなたの場合、それらはすべて同じスレッドを指します。

例を機能させたい場合は、それぞれが異なる(コピー)ThreadLocalを指す必要があります。ArrayList

myThreadLocal.set(new ArrayList<Integer>(value));

すべてが同じオブジェクトをThreadLocal指していることは、この場合、グローバルに利用可能な単一の参照のみが必要であるため、あまり意味がありません。

于 2012-07-06T10:26:46.747 に答える
2

同じリスト参照を2つのスレッドローカル変数内に格納しました。これは、ThreadLocalにスレッドごとの値がないという意味ではありません。テストでは、スレッドローカルに何かを格納する1つのスレッドを開始してから、スレッドローカル変数に何かが含まれているかどうかを確認する別のスレッドを開始する必要があります(含まれません)。

これは、2つのマップがあり、両方のマップに同じリストを保存した場合とまったく同じです。もちろん、一方のマップに保存されているリストを変更すると、同じリストであるため、もう一方のマップに保存されているリストも変更されます。ただし、一方のマップをクリアしても、もう一方のマップはクリアされません。

于 2012-07-06T10:30:41.603 に答える
1

ThreadLocalは、各スレッドに異なる参照を強制するのではなく、設定方法に応じて、各スレッドが独自のコピーを持つ可能性があります。

各オブジェクトが独自のフィールドを持っているのと同じように、すべてのオブジェクトのそのフィールドを同じ値に設定することも、異なる値を設定することもできます。

java.lang.Threadsクラスのソースを読んで、ThreadLocalが実際にどのように実装されているかを確認することをお勧めします。

于 2012-07-06T11:02:20.810 に答える