并发编程基础之ThreadLocal
一:概念
在多线程并发访问的情况下,为了解决线程安全,一般我们会使用synchronized关键字,如果并发访问量不是很大,可以使用synchronized,
但是如果数据量比较大,我们可以考虑使用ThreadLocal,顾名思义,就是线程的本地存储,对于类中的成员变量,如果多个线程同时访问
就会存在线程安全问题,ThreadLocal提供给我们不同于synchronized的另外一种思路,就是把变量值在每个线程存储副本
如下示例:
/** * */ package com.hlcui.main; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @author Administrator * */ public class ThreadLocalDemo { //保留变量在线程中的副本 private ThreadLocal<String> threadLocal = new ThreadLocal<String>(); private void set(String name) { threadLocal.set(name); } private String get() { return threadLocal.get(); } public static void main(String[] args) { final ThreadLocalDemo demo = new ThreadLocalDemo(); ExecutorService executors = Executors.newFixedThreadPool(2); executors.execute(new Runnable() { @Override public void run() { demo.set("tom"); String threadName = Thread.currentThread().getName(); System.out.println(threadName+":::"+demo.get()); } }); executors.execute(new Runnable() { @Override public void run() { demo.set("jack"); String threadName = Thread.currentThread().getName(); System.out.println(threadName+":::"+demo.get()); } }); executors.shutdown(); } }
运行结果:
pool-1-thread-1:::tom pool-1-thread-2:::jack
通过结果可以看出同一个实例的同一个方法,不同的线程获取的结果是不一样的。
示例二:
测试5个线程计数:
/** * */ package com.hlcui.main; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * @author Administrator * */ public class ThreadDemo2 { public static void main(String[] args) { ExecutorService executors = Executors.newFixedThreadPool(5); for (int i = 0; i < 5; i++) { executors.execute(new ThreadHolder(i)); } try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } executors.shutdown(); } } class ThreadHolder implements Runnable { private final int id; ThreadHolder(int i) { this.id = i; } private static ThreadLocal<Integer> tl = new ThreadLocal<Integer>() { Random r = new Random(47); public synchronized Integer initialValue() { return r.nextInt(100); } }; public static void increment() { tl.set(tl.get() + 1); } @Override public void run() { System.out.println(this); ThreadHolder.increment(); System.out.println(this); } public String toString() { return "id:::"+id+", "+tl.get(); } }
运行结果:
id:::0, 58 id:::1, 55 id:::2, 93 id:::0, 59 id:::2, 94 id:::1, 56 id:::3, 61 id:::3, 62 id:::4, 61 id:::4, 62