Sharing data is one of the core problems of concurrent programs, which is especially important for objects that inherit the thread class or implement the Runnable interface. If you create an instance of a class that implements the Runnable interface, create multiple thread objects with it as an incoming parameter and start those threads, all the threads will share the same properties. That is, if you change a property in one thread, all threads will be affected by this change.
In some cases, the properties of this object do not need to be shared by all threads. The Java Concurrency API provides a clean mechanism, the thread local variable (thread-local Variable), which has good performance.
Here we will create two programs: The first one has the problem just mentioned. Another use of the thread-local variable mechanism solves this problem.
The first example shows a problem with sharing before it is Born:
package concurrency;import java.util.date;import java.util.concurrent.timeunit;public Class main3 { public static void main (String[] args) { unsafetask task = new unsafetask (); for (int i=0; i<10;i++) { thread thread = new thread (Task); thread.start (); try { timeunit.seconds.sleep (2); } catch (interruptedexception e) { e.printstacktrace (); } } }} class unsafetask implements runnable{ private date startdate; @Override public void run () { startdate = new date (); system.out.printf ("starting thread: %s : %s\n", Thread.CurrentThread (). GetId (), StartDate); try { timeunit.seconds.sleep ((int) Math.rint ( Math.random () *10)); } catch (InterruptedException e) &NBSP;{&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSp; e.printstacktrace (); } system.out.printf ("thread finished: %s : %s\n ", thread.currentthread (). GetId (), startdate); }}
The second example, which solves the problem in the first example with a thread-local variable:
package concurrency;import java.util.date;import java.util.concurrent.timeunit;public Class main4 { public static void main (String[] args) { safetask task = new safetask (); for (int i=0; i<10;i++) { thread thread = new thread (Task); thread.start (); try { timeunit.seconds.sleep (2); } catch (interruptedexception e) { &nbSp; e.printstacktrace (); } } }}class SafeTask implements Runnable{ private static Threadlocal<date> startdate = new threadlocal<date> () { protected date initialvalue () { return new date (); } }; @Override public void run () { system.out.printf ("starting thread: %s : %s\n ", thread.currentthread (). GetId (), Startdate.get ()); try {&nbSp; timeunit.seconds.sleep ((int) Math.rint ( Math.random () *10)); } catch (InterruptedException e) { e.printstacktrace (); } System.out.printf ("thread finished: %s : %s\n", Thread.CurrentThread (). GetId (), Startdate.get ()); }}
Declares a Threadlocal<date> object. The object of date is implicitly implemented in the InitialValue () method, and this method returns the current date. Thread-local variables store their own property values for each thread, respectively, and are provided to each thread for use. You can use the Get () method to read this value and set it with the set () method. If the thread is accessing a thread-local variable for the first time, the thread-local variable may not have stored a value for it, and this time the InitialValue () method is called and the current time value is returned.
The thread local variable also provides the Remove () method, which is used to delete the stored value for the thread that accesses the variable. The Java Concurrency API contains the Inheritablethreadlocal class, which provides inherited values if a thread is created from another thread. If a thread a threads local variable already has a value, when it creates another thread B, thread B's thread local variable will be the same as thread A. You can override the Childvalue () method, which is used to initialize the values in the thread local variables of the child threads, using the values in the thread local variables of the parent threads as incoming parameters.
Use of thread Local variables