Example illustrates the ThreadLocal class for concurrent Java programming

  • 2020-04-01 03:49:18
  • OfStack

The ThreadLocal class, which can be understood as ThreadLocalVariable(thread-local variable), provides access interfaces or methods such as get and set that hold a separate copy for each thread that USES the variable, so get always returns the latest value set by the currently executing thread when it calls set. Can be ThreadLocal< T> Considered to include Map< Thread, T> Object that holds values specific to that thread.

To summarize, for the problem of multi-threaded resource sharing, synchronization takes a time-for-space approach, while ThreadLocal takes a space-for-time approach. The former provides only one variable to be queued for access by different threads, while the latter provides one variable for each thread, so it can be accessed at the same time without affecting each other.

To simulate the ThreadLocal


import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
 
public class SimpleThreadLocal<T> {
 private Map<Thread, T> valueMap = Collections
   .synchronizedMap(new HashMap<Thread, T>());
 
 public void set(T newValue) {
  valueMap.put(Thread.currentThread(), newValue); //Key for the thread object, the value of the thread of the variable copy
 }
 
 public T get() {
  Thread currentThread = Thread.currentThread();
  T o = valueMap.get(currentThread); //Returns the variable
corresponding to this thread   if (o == null && !valueMap.containsKey(currentThread)) { //If it does not exist in the Map, save it in the Map. < br / >    o = initialValue();
   valueMap.put(currentThread, o);
  }
  return o;
 }
 
 public void remove() {
  valueMap.remove(Thread.currentThread());
 }
 
 protected T initialValue() {
  return null;
 }
}

Practical ThreadLocal

class Count {
 private SimpleThreadLocal<Integer> count = new SimpleThreadLocal<Integer>() {
  @Override
  protected Integer initialValue() {
   return 0;
  }
 };
 
 public Integer increase() {
  count.set(count.get() + 1);
  return count.get();
 }
 
}
 
class TestThread implements Runnable {
 private Count count;
 
 public TestThread(Count count) {
  this.count = count;
 }
 
 @Override
 public void run() {
  // TODO Auto-generated method stub
  for (int i = 1; i <= 3; i++) {
   System.out.println(Thread.currentThread().getName() + "t" + i
     + "tht" + count.increase());
  }
 }
}
 
public class TestThreadLocal {
 public static void main(String[] args) {
  Count count = new Count();
  Thread t1 = new Thread(new TestThread(count));
  Thread t2 = new Thread(new TestThread(count));
  Thread t3 = new Thread(new TestThread(count));
  Thread t4 = new Thread(new TestThread(count));
  t1.start();
  t2.start();
  t3.start();
  t4.start();
 }
}

The output

Thread-0    1th    1
Thread-0    2th    2
Thread-0    3th    3
Thread-3    1th    1
Thread-1    1th    1
Thread-1    2th    2
Thread-2    1th    1
Thread-1    3th    3
Thread-3    2th    2
Thread-3    3th    3
Thread-2    2th    2
Thread-2    3th    3


Related articles: