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 方法;因此即使不人工释放资源也不会造成内存溢出。