一:概念java
在多線程併發訪問的狀況下,爲了解決線程安全,通常咱們會使用synchronized關鍵字,若是併發訪問量不是很大,能夠使用synchronized,安全
可是若是數據量比較大,咱們能夠考慮使用ThreadLocal,顧名思義,就是線程的本地存儲,對於類中的成員變量,若是多個線程同時訪問多線程
就會存在線程安全問題,ThreadLocal提供給咱們不一樣於synchronized的另一種思路,就是把變量值在每一個線程存儲副本併發
以下示例:dom
/** * */ 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(); } }
運行結果:ide
pool-1-thread-1:::tom pool-1-thread-2:::jack
經過結果能夠看出同一個實例的同一個方法,不一樣的線程獲取的結果是不同的。測試
示例二:ui
測試5個線程計數:this
/** * */ 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