threadlocal set方法是不是线程安全的

 我来答
中华好文章
2016-08-12 · 尽力提供优质内容,感谢大家
中华好文章
采纳数:739 获赞数:3993

向TA提问 私信TA
展开全部
ThreadLocal的核心概念是没一个线程可以通过get或者set方法访问它自己的、独立初始化的变量的副本。

1. ThreadLocal介绍
为了在多线程环境下不出现任何的冲突,我们希望能否分离一个类的多个实例。对于每一个线程来说,没一个实例都是唯一的。这不过是实现线程安全的一个方式。
线程安全的另外的重要的一点是能够全局访问。可以在线程内部的任何地方进行访问。记住:应该声明成static和final的。

2. 什么是线程安全
线程是进程的一条单独的线。当我们提到多线程应用的时候,我们的意思是一个进程的多个线程访问同一行代码。在这个情况下,存在一个线程访问或者修改另一个线程的数据的可能性。当数据不允许这样共享的时候,我们应该做成线程安全的。实现线程安全的方式有下面几种:
· 重入
·互斥(同步机制)
·ThreadLocal
·原子操作
3. 使用ThreadLocal
(引用Joshua Bloch的一段话,巨抽象,我没看懂,......)
我们有一个非线程安全的变量,我们想把它变成线程安全的,可以考虑同步机制把对象封闭到同步块中。另外的方式是使用ThreadLocal,为每一个线程持有单独的对象使得变得安全。

4. ThreadLocal的例子

package com.javapapers;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadLocalExample {
private static final ThreadLocal formatter = new ThreadLocal() {

protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyyMMdd HHmm");
}
};

public String formatIt(Date date) {
return formatter.get().format(date);
}
}

上边的代码中,关键要理解get()方法。他返回的当前线程的ThreadLocal变量的副本。如果当前线程的这个变量还没有值,则通过调用initalValue方法返回第一次初始化的值。

JavaDoc中的例子

下面的例子为每一个线程生成一个唯一的标识符。第一次调用get方法的时候指定一个线程的id,并且在随后的调用中保持不变。

port java.util.concurrent.atomic.AtomicInteger;

public class ThreadId {
// Atomic integer containing the next thread ID to be assigned
private static final AtomicInteger nextId = new AtomicInteger(0);

// Thread local variable containing each thread's ID
private static final ThreadLocal threadId =
new ThreadLocal() {
@Override protected Integer initialValue() {
return nextId.getAndIncrement();
}
};

// Returns the current thread's unique ID, assigning it if necessary
public static int get() {
return threadId.get();
}
}

5. Java API中ThreadLocal 的使用
在JDK1.7中,我们有一个叫做ThreadLocalRandom的新类。它用于为并行的线程生成随机数,每一个线程是随机数的种子都是唯一的。这是一个非常酷的功能。
下面的代码是上边的类实现ThreadLocal 的代码:

private static final ThreadLocal localRandom =
new ThreadLocal() {
protected ThreadLocalRandom initialValue() {
return new ThreadLocalRandom();
}
};

使用ThreadLocalRandom

package com.javapapers;

import java.util.concurrent.ThreadLocalRandom;

public class ThreadLocalRandomExample {

public static void main(String args[]) throws InterruptedException {

//tossing 3 coins
for (int i = 0; i < 3; i++) {
final Thread thread = new Thread() {

public void run() {
System.out.print(Thread.currentThread().getName() + ":");

// generating 3 random numbers - random for every thread
for (int j = 0; j < 3; j++) {
final int random = ThreadLocalRandom.current().nextInt(
1, 3);
System.out.print(random + ",");
}
System.out.println();
}
};
thread.start();
thread.join();
}
}
}

6. ThreadLocal和内存泄露
ThreadLocal不是一个魔鬼,而是一个优秀的、实用的API。完全取决于我们怎么样去使用。我们应该学会在正确的场合使用合适的工具。我们不能使用大炮打蚊子,但是也不能谴责大炮。
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式