単なる言葉よりも、我々はThreadLocalをの役割の例を見て、より直感的である必要はあり;問題に良い方法を解決するため、マルチスレッドを提供するためのThreadLocal
import java.util.Random;
public class Test {
private static int data = 0;
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
data = new Random().nextInt();
System.out.println(Thread.currentThread().getName()+" has put data "+data);
new A().get();
new B().get();
}
}).start();
}
static class A{
public void get() {
System.out.println("A from "+Thread.currentThread().getName()+" has get data "+data);
}
}
static class B{
public void get() {
System.out.println("B from "+Thread.currentThread().getName()+" has get data "+data);
}
}
}
执行结果:
Thread-0 has put data 1902290541
A from Thread-0 has get data 1902290541
B from Thread-0 has get data 1902290541
試験における静的変数データがある;この例は、非常に単純なスレッドであり、このデータは、データスレッドで共有され、データは、その後、乱数を再度割り当てるAを呼び出し、メソッドの出力クラスBであり得るために1回の作動スレッドがあろうそのデータ値は、上記の結果。
質問は、あるスレッドがより多くのそれを、その後、出力に確かに何も影響はありませんか?二つの例をテストするために、ここで、
import java.util.Random;
public class Test {
private static int data = 0;
public static void main(String[] args) {
for(int i=1;i<=2;i++) {
new Thread(new Runnable() {
@Override
public void run() {
data = new Random().nextInt();
System.out.println(Thread.currentThread().getName()+" has put data "+data);
new A().get();
new B().get();
}
}).start();
}
}
static class A{
public void get() {
System.out.println("A from "+Thread.currentThread().getName()+" has get data "+data);
}
}
static class B{
public void get() {
System.out.println("B from "+Thread.currentThread().getName()+" has get data "+data);
}
}
}
まったく同じスレッドの複雑さ、我々は2を実行し、私たちが望む結果が得られた:2個の乱数を使用した取得し、A、得られたクラスBに乱数の出力方法を取得します。結果は、我々はの実装の結果のほとんどを発見しました次のように:
私たちは、ここで得られた結果は、我々が望むものではないことがわかったが、なぜそのような結果はありますか?、したがって、私は実行するどこにある二つのスレッドを実行し、スレッドの複雑さは、(私たちの例のように)同じである場合、スレッドはほとんど行うピアの機会をつかむ、実行のプリエンプティブスレッド:簡単です我々は、一例として実行するために2つのスレッド(スレッド1とスレッドの最初のforループである)を有する:データ=新しいランダムに実行の2つのスレッド()nextInt()は、新たなランダム値を取得し、そしてためのスレッドと。 2スレッドピアを実行する機会をつかむため、権限を実行しているスレッドをつかむ、次の実行がオンに変更されているように、ランダムな値は、2つのスレッドを取得し、新しいランダム値とカバーを取得するためにコードの行を実行します図の出力結果。
私たちは、その後、別の言い方をする、我々は共有乱数値を定義し、地図として取得したデータを出力します。
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class Test {
private static Map<Thread, Integer> threadData = new HashMap<Thread, Integer>();
public static void main(String[] args) {
for(int i=1;i<=2;i++) {
new Thread(new Runnable() {
@Override
public void run() {
int data = new Random().nextInt();
System.out.println(Thread.currentThread().getName()+" has put data "+data);
threadData.put(Thread.currentThread(), data);
new A().get();
new B().get();
}
}).start();
}
}
static class A{
public void get() {
int data = threadData.get(Thread.currentThread());
System.out.println("A from "+Thread.currentThread().getName()+" has get data "+data);
}
}
static class B{
public void get() {
int data = threadData.get(Thread.currentThread());
System.out.println("B from "+Thread.currentThread().getName()+" has get data "+data);
}
}
}
次のように実行結果は以下のとおりです。
このアプローチは、私たちが望む結果を得ることができますが、地図が手動解除を作成する必要ですが、リリースされていない場合は、スレッドの実行の多くは、すぐにメモリをオーバーフローします、したがって、この方法はまだ望ましいことではありません。
その後、ThreadLocalの利点が明らかになり、同期の方法は同様に、データを手動でクリーンアップする必要があります。
ThreadLocalの データ共有:
import java.util.Random;
public class Test {
static ThreadLocal<Integer> x = new ThreadLocal<Integer>();
public static void main(String[] args) {
for(int i=0;i<=1;i++) {
new Thread(new Runnable() {
@Override
public void run() {
int data = new Random().nextInt();
System.out.println(Thread.currentThread().getName()+" has put data "+data);
x.set(data);
new A().get();
new B().get();
}
}).start();
}
}
static class A{
public void get() {
int data = x.get();
System.out.println("A from "+Thread.currentThread().getName()+" has get data "+data);
}
}
static class B{
public void get() {
int data = x.get();
System.out.println("B from "+Thread.currentThread().getName()+" has get data "+data);
}
}
}
次のように実行結果は以下のとおりです。
確認した目は、私たちが必要とするデータである。そして、その設定方法を見てみましょう。
是采用的 set 方法存储数据,而不是 put 方法;因此即使不人工释放资源也不会造成内存溢出。