ThreadLocal 初试
2016-06-16 16:00
423 查看
ThreadLocal 学习一下
之前就接触过好多次这个类,一直没搞明白这货是啥,怎么个用法,今天仔细研究一下,原来用法很简单;只是没有使用场景,学的容易忘的更容易罢了,记录一下,以作备忘;
ThreadLocal到底是什么?
字面意思好像是本地线程,不太贴切,并不是一个线程, “线程本地变量表”更合适一些,就是用来存储线程私有的变量;大家都知道,一个类,如果有属性,不加同步控制的话,并发访问的情况下,结果是不可预测的,数据会在多个线程之间窜,ThreadLocal解决了这个问题;
ThreadLocal为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。
OK,现在清楚了,辣么使用场景也就知道了:让我们可以在多线程环境下不用加锁,而又能安全的访问公共对象的属性;
前辈告诉我们,能用代码解决的问题就不要讲道理,那么上栗子:
首先看看不使用ThreadLocal, 定义一个Runnable,她有一个属性:
package net.tt.web.stu.concurrent.threadlocal; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author tbc * @version 1.0 {2016年6月16日 下午3:42:29} */ public class NoThreadLocal implements Runnable { private Logger log = LoggerFactory.getLogger(NoThreadLocal.class); private String str = new String("str"); @Override public void run() { // 先读取 log.info("one -> Trhead: {}, var: {}", Thread.currentThread().getName(), str); // 再写入 str = Thread.currentThread().getName(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } // 再读取 log.info("two -> Trhead: {}, var: {}", Thread.currentThread().getName(), str); } public static void main(String[] args) { NoThreadLocal t = new NoThreadLocal(); new Thread(t, "a").start(); new Thread(t, "b").start(); new Thread(t, "c").start(); } }
我们实例化一个此类的对象,然后起多个线程去调用,很明显,结果是不可预知的:
乱了,每个线程拿到的值都是a,怎么办呢?当然可以加锁:
public synchronized void setStr(String str) { this.str = str; }
如果不想加锁呢?这个时候ThreadLocal 可以出场 :
package net.tt.web.stu.concurrent.threadlocal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author tbc * @version 1.0 {2016年6月16日 下午3:30:39} */ public class ThreadLocalTest implements Runnable { private Logger log = LoggerFactory.getLogger(ThreadLocalTest.class); private static final ThreadLocal<String> var = new ThreadLocal<String>(); @Override public void run() { // 先读取 log.info("one -> Trhead: {}, var: {}", Thread.currentThread().getName(), getThreadLocal().get()); // 再写入 var.set(Thread.currentThread().getName()); // 停一下等其它线程跑偏 try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } // 再读取 log.info("two -> Trhead: {}, var: {}", Thread.currentThread().getName(), getThreadLocal().get()); } public ThreadLocal<String> getThreadLocal() { String a = var.get(); if (a == null) { var.set("init"); } return var; } public static void main(String[] args) { ThreadLocalTest t = new ThreadLocalTest(); new Thread(t, "a").start(); new Thread(t, "b").start(); new Thread(t, "c").start(); } }
现在就好了,我们的目的达到了:
perfect!
<
4000
/article>
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- 使用 Syncthing 在多个设备间同步文件
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序