詳細ThreadLocalの

単なる言葉よりも、我々は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 方法;因此即使不人工释放资源也不会造成内存溢出。

发布了99 篇原创文章 · 获赞 3 · 访问量 1204

おすすめ

転載: blog.csdn.net/qq_44971038/article/details/104535915