您的位置:首页 > 编程语言 > Java开发

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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息