如果你定义了一个单实例的java bean,它有若干属性,但是有一个属性不是线程安全的,比如说HashMap。并且碰巧你并不需要在不同的线程中共享这个属性,也就是说这个属性不存在跨线程的意义。那么你不要sychronize这么复杂的东西,ThreadLocal将是你不错的选择。

举例来说:

package threadlocal;

import java.util.TreeMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class TreadLocalTest { static ThreadLocal<TreeMap<String, Integer>> map0 = new ThreadLocal<TreeMap<String, Integer>>() {
@Override
protected TreeMap<String, Integer> initialValue() {
System.out.println(Thread.currentThread().getName() + ":initialValue");
return new TreeMap<String, Integer>();
}
}; public void run() {
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < 3; i++) {
es.execute(new Task(i));
}
es.shutdown();
} public static class Task implements Runnable {
private int id; public Task(int id) {
this.id = id;
} public void run() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + ":start");
TreeMap<String, Integer> map = map0.get();
for (int i = 0; i < 5; i++) {
map.put(threadName + ":" + i, i + id * 100);
try {
Thread.sleep(100);
} catch (Exception ex) {
ex.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + ':' + map);
}
} public static void main(String[] args) {
TreadLocalTest test = new TreadLocalTest();
test.run();
} }

输出解释;

pool-1-thread-1:start
pool-1-thread-1:initialValue
pool-1-thread-2:start
pool-1-thread-2:initialValue
pool-1-thread-3:start
pool-1-thread-3:initialValue
pool-1-thread-1:{pool-1-thread-1:0=0, pool-1-thread-1:1=1, pool-1-thread-1:2=2, pool-1-thread-1:3=3, pool-1-thread-1:4=4}
pool-1-thread-2:{pool-1-thread-2:0=100, pool-1-thread-2:1=101, pool-1-thread-2:2=102, pool-1-thread-2:3=103, pool-1-thread-2:4=104}
pool-1-thread-3:{pool-1-thread-3:0=200, pool-1-thread-3:1=201, pool-1-thread-3:2=202, pool-1-thread-3:3=203, pool-1-thread-3:4=204}

可以看到map0 虽然是个静态变量,但是initialValue被调用了三次,通过debug发现,initialValue是从map0.get处发起的。而且每个线程都有自己的map,虽然他们同时执行。

进入Theadlocal代码,可以发现如下的片段;

public T get() { 
        Thread t = Thread.currentThread(); 
        ThreadLocalMap map = getMap(t); 
        if (map != null) { 
            ThreadLocalMap.Entry e = map.getEntry(this); 
            if (e != null) 
                return (T)e.value; 
        } 
        return setInitialValue(); 
    }

这说明ThreadLocal确实只有一个变量,但是它内部包含一个map,针对每个thread保留一个entry,如果对应的thread不存在则会调用initialValue。

http://www.cnblogs.com/alphablox/archive/2013/01/20/2869061.html

package threadlocal;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /*2015-9-15*/
public class KeepObjectStatus { private int times = -1; public int getTimes() {
return times;
} public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(new Task(2));
executor.execute(new Task(5));
executor.shutdown();
} public void process() {
if (times < 10) {
times++;
}
} public static ThreadLocal<KeepObjectStatus> instance = new ThreadLocal<KeepObjectStatus>() { @Override
protected KeepObjectStatus initialValue() {
System.out.println(Thread.currentThread() + " begin to init");
return new KeepObjectStatus();
} }; } class Task implements Runnable { private int step; public Task(int step) {
super();
this.step = step;
} @Override
public void run() { KeepObjectStatus kos = KeepObjectStatus.instance.get();
for (int i = 0; i < 10; i += step) {
kos.process();
System.out.println(String.format("%s==> Step:%s %d", Thread.currentThread(), step, kos.getTimes()));
}
} }

Output:

Thread[pool-1-thread-1,5,main]  begin to init
Thread[pool-1-thread-2,5,main] begin to init
Thread[pool-1-thread-2,5,main]==> Step:5 0
Thread[pool-1-thread-1,5,main]==> Step:2 0
Thread[pool-1-thread-2,5,main]==> Step:5 1
Thread[pool-1-thread-1,5,main]==> Step:2 1
Thread[pool-1-thread-1,5,main]==> Step:2 2
Thread[pool-1-thread-1,5,main]==> Step:2 3
Thread[pool-1-thread-1,5,main]==> Step:2 4

ThreadLocal用法和实现原理(转)的更多相关文章

  1. ThreadLocal用法和实现原理

    如果你定义了一个单实例的java bean,它有若干属性,但是有一个属性不是线程安全的,比如说HashMap.并且碰巧你并不需要在不同的线程中共享这个属性,也就是说这个属性不存在跨线程的意义.那么你不 ...

  2. java.lang.ThreadLocal的作用和原理?列举在哪些程序中见过ThreadLocal的使用?

    java.lang.ThreadLocal的作用和原理?列举在哪些程序中见过ThreadLocal的使用? 说明类java.lang.ThreadLocal的作用和原理.列举在哪些程序中见过Threa ...

  3. ThreadLocal及InheritableThreadLocal的原理剖析

    我们知道,线程的不安全问题,主要是由于多线程并发读取一个变量而引起的,那么有没有一种办法可以让一个变量是线程独有的呢,这样不就可以解决线程安全问题了么.其实JDK已经为我们提供了ThreadLocal ...

  4. ThreadLocal的使用及原理分析

    文章简介 ThreadLocal应该都比较熟悉,这篇文章会基于ThreadLocal的应用以及实现原理做一个全面的分析 内容导航 什么是ThreadLocal ThreadLocal的使用 分析Thr ...

  5. ThreadLocal系列(一)-ThreadLocal的使用及原理解析

    ThreadLocal系列之ThreadLocal(源码基于java8) 项目中我们如果想要某个对象在程序运行中的任意位置获取到,就需要借助ThreadLocal来实现,这个对象称作线程的本地变量,下 ...

  6. 在spring+beranate中多数据源中使用 ThreadLocal ,总结的原理 --费元星

    设计模式 首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问 ...

  7. ThreadLocal的使用及原理解析

    # 基本使用 JDK的lang包下提供了ThreadLocal类,我们可以使用它创建一个线程变量,线程变量的作用域仅在于此线程内.<br />用2个示例来展示一下ThreadLocal的用 ...

  8. 多线程爬坑之路-ThreadLocal源码及原理的深入分析

    ThreadLocal<T>类:以空间换时间提供一种多线程更快捷访问变量的方式.这种方式不存在竞争,所以也不存在并发的安全性问题. This class provides thread-l ...

  9. Spring Boot的Listener机制的用法和实现原理详解

    之前在介绍了在spring-boot启动过程中调用runner的原理,今天我们介绍另外一种可以实现相似功能的机制:spring-boot的Listener机制. 通过注册Listener,可以实现对于 ...

随机推荐

  1. java线程池分析和应用

    比较 在前面的一些文章里,我们已经讨论了手工创建和管理线程.在实际应用中我们有的时候也会经常听到线程池这个概念.在这里,我们可以先针对手工创建管理线程和通过线程池来管理做一个比较.通常,我们如果手工创 ...

  2. 「OC」 多态

    一.基本概念 多态在代码中的体现,即为某一类事物的多种形态,OC对象具有多态性.必须要有继承,没有继承就没有多态. 在使用多态时,会进行动态检测,以调用真实的对象方法. 多态在代码中的体现即父类指针指 ...

  3. Linux下载文件时报错 To connect to ohse.de insecurely, use ‘--no-check-certificate’.

    远程调用下载文件直接用wget就可以,一般文件路径类型是http.如果有遇到是https就会下载出错. 错误如下: [root@vmu010226-node1 tmp]# wget https://w ...

  4. php随机10-thinkphp 3.1.3 模板继承 布局

    8.25 模板继承 模 板继承是3.1.2版本添加的一项更加灵活的模板布局方式,模板继承不同于模板布局,甚至来说,应该在模板布局的上层.模板继承其实并不难理解,就好比类 的继承一样,模板也可以定义一个 ...

  5. U-Boot在FL2440上移植(三)----支持NAND Flash

    <一>支持NAND Flash 1. 首先在配置文件 include/config/fl2440.h 的宏 CONFIG_COMMANDS 中增加 CFG_CMD_NAND, #defin ...

  6. iOS开发之SDWebImage详解

    介绍 github地址: https://github.com/rs/SDWebImage 简介 一个异步图片下载及缓存的库 特性: 一个扩展UIImageView分类的库,支持加载网络图片并缓存图片 ...

  7. 蝕刻技術(Etching Technology)

    1. 前言 蚀刻是将材料使用化学反应或物理撞击作用而移除的技术. 蚀刻技术可以分为『湿蚀刻』(wet etching)及『干蚀刻』(dry etching)两类.在湿蚀刻中是使用化学溶液,经由化学反应 ...

  8. java面板设计

    写面板真的是写到吐血,深深感受到什么叫又臭又长,可能是自己用的太烂吧. 关于布局管理器不写一下还是不懂,另外加面板的思想跟html中div的感觉差不多. 发现的一个小彩蛋:用JScrollPane的时 ...

  9. Codeforces 360C Levko and Strings dp

    题目链接:点击打开链接 题意: 给定长度为n的字符串s,常数k 显然s的子串一共同拥有 n(n-1)/2 个 要求找到一个长度为n的字符串t,使得t相应位置的k个子串字典序>s #include ...

  10. HTML高级选项卡(1)————表标签

    利用上述表格属性,能够简单的创建一个表格.并随意的分割行和列. <html> <head> <title>表格的应用</title> </head ...