Detailed ThreadLocal

ThreadLocal to provide multi-threaded solve the problem a good way; more than just words, we have to be more intuitive to see examples of the role of 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

This example is a very simple thread; there is a static variable data in Test; and this data is shared data thread; threads per actuation will be for data re-assign a random number, then call A, get Method output class B is its data value; the results above.

The question is, is certainly a thread no effect on the output, then more of it? Here to test the example, two;

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);
		}
	}
}

Exactly the same thread complexity; we execute two, had the results we want: Get two random numbers were used and A, get random numbers output method in class B obtained; the results we found that most of the results of the implementation of as follows:

We found that the results obtained here is not what we want, but why is there such a result? Is simple: preemptive thread of execution, when the complexity of the threads are the same (as in our example), the thread seize the opportunity to perform almost peer; therefore execute two threads where you are where I perform, we have 2 threads (that is, for the first loop of thread, with the thread 1) to perform as an example: 2 threads of execution to data = new random () nextInt (); get a new random value; and because a thread and. 2 thread seize the opportunity to perform a peer, so grab a thread executing authority, execute the line of code to get a new random value and covers random values ​​obtained 2 threads, so the next execution has changed on FIG output result;

We then put it another way, we define a shared random number value and outputs the acquired data as Map:

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);
		}
	}
}

Execution results are as follows:

While this approach can get the result we want, but Map is the need to create a manual release, if not released, a lot of thread execution, will soon overflow the memory, therefore, this method is still not desirable;

synchronized methods Likewise, you need to manually clean up the data; then ThreadLocal advantage becomes obvious;

ThreadLocal  data sharing:

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);
		}
	}
}

Execution results are as follows:

Confirmed eyes, is the data we need; then look at its set method:

是采用的 set 方法存储数据,而不是 put 方法;因此即使不人工释放资源也不会造成内存溢出。

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

Guess you like

Origin blog.csdn.net/qq_44971038/article/details/104535915
Recommended