线程范围内的共享变量,每个线程只能访问他自己的,不能访问别的线程的。
下面请看一个不安全的例子,这个例子中的data数据有安全问题,可以测试一下
view plain
import java.util.Random;
public class ThreadScopeShareData {
public static int data;
/**
* @param args
*/
public static void main(String[] args) {
for(int i=0;i<2;i++){
new Thread(new Runnable(){
@Override
public void run() {
data = new Random().nextInt();
new ThreadA().getData();
new ThreadB().getData();
}
}).start();
}
}
static class ThreadA{
public void getData(){
System.out.println("ThreadA -- " + Thread.currentThread().getName()+"-data=" + data);
}
}
static class ThreadB{
public void getData(){
System.out.println("ThreadB -- " + Thread.currentThread().getName()+"-data=" + data);
}
}
}
对与上述程序如何修改呢,就是实现一个类似于ThreadLocal的类一种实现,就是创建一个Map集合,键是线程自己,数据是data,取数据的时候就不会取错了。
代码如下:
view plain
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class ThreadScopeShareData {
public static int data;
public static Map
dataMap = new HashMap();
/**
* @param args
*/
public static void main(String[] args) {
for(int i=0;i<2;i++){
new Thread(new Runnable(){
@Override
public void run() {
data = new Random().nextInt();
dataMap.put(Thread.currentThread(), data);
new ThreadA().getData();
new ThreadB().getData();
}
}).start();
}
}
static class ThreadA{
public void getData(){
System.out.println("ThreadA -- " + Thread.currentThread().getName()+"-data=" + dataMap.get(Thread.currentThread()));
}
}
static class ThreadB{
public void getData(){
System.out.println("ThreadB -- " + Thread.currentThread().getName()+"-data=" + dataMap.get(Thread.currentThread()));
}
}
}
这种实现方式类似于一些大型框架的底层实现。可以好好的看一下。
ThreadLocal
其实 ThreadLocal 并非是一个线程的本地实现,它并不是一个 Thread ,而是 Thread Local Variable(线程局部变量),它的功能就是为每一个使用该变量的线程 提供一个变量值的副本,每一个线程都可以独立地改变自己的副本而不影响其它线程。从线程的角度来看,就好像没一个线程都完全拥有该变量。
ThreadLocal 与其它线程同步机制的区别
ThreadLocal 与其它同步机制都是为了解决多线程中对同一变量的访问冲突,在普通的同步机制中,是通过对象加锁来实现多个线程对同一变量的安全访问,这时该变量是多个线 程共享的,使用这种同步机制需要很细致的分析出某时是哪个线程在操作该变量。 ThreadLocal 是从另一个角度来解决多线程的并发访问,ThreadLocal 会为每一个线程管理一个和该线程绑定的变量副本,从而隔离了对歌线程的数据,每一个线程都拥有自己的变量副本,因此也没有必要对该变量同步了。 ThreadLocal 并不能代替其它同步机制,两者面向的方向不同。其它同步机制是为了同步多个线程对相同资源的并发访问,是为了对个线程之间进行通信的有效方式,而 ThreadLocal 是隔离多个线程的数据共享,从根本上就不存在多个线程的共享资源。所以,如果你需要进行多个线程之间的通信,则使用同步机制,如果需要隔离多个线程之间的 共享冲突,可以使用 ThreadLocal ,这将极大简化代码量,并且美观易读。
ThreadLocal 内部机制
在 ThreadLocal 中,有一个Map集合,其中线程的对象引用作为键(key),而值(value)存放的是你丢进去的对象。对于同一个线程返回的是同一个 value,不同的线程返回的是不同的 value。这是通过 ThreadLocal 的 set()、get()
方法
快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载
实现的。在某一个线程结束前,应当清除存放在 ThreadLocal 中的对象,否则会导致服务器存放过多的垃圾。清除对象的方法是,在该线程下,调用 ThreadLocal 对象的 remove() 方法。
ThreadLocal 常见方法
void set(Object value) 设置当前线程的局部变量的值
Object get() 返回当前线程的局部变量的值
void remove() 将当前线程的局部变量的值删除,目的是为了减少内存占用。 当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
protected Object intialValue 返回该线程的局部变量的初始值。该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用 get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。
举例说明 ThreadLocal 的使用方法
编写代码,实现5个线程对同一对象的访问,并且保证在一个线程内获取的对象是同一个对象。
view plain
HYPERLINK "http://blog.csdn.net/driverking/article/details/6557513#"print
HYPERLINK "http://blog.csdn.net/driverking/article/details/6557513#"?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
import java.util.Random;
public class Demo {
public static void main(String[] args) {
final A a = new A();
final B b = new B();
for (int i = 0; i < 5; i++) {
new Thread() {
public void run() {
MyThredLocal.getInstance().setIndex(
new Random().nextInt(100));
a.getA();
b.getB();
};
}.start();
MyThredLocal.clear();
}
}
}
class MyThredLocal {
private MyThredLocal() {
}
public static ThreadLocal instanceContainer = new ThreadLocal();
private int index;
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public static MyThredLocal getInstance() {
MyThredLocal instance = instanceContainer.get();
if (instance == null) {
if (instance == null) {
instance = new MyThredLocal();
instanceContainer.set(instance);
}
}
return instance;
}
public static void clear() {
instanceContainer.remove();
}
}
class A {
public void getA() {
MyThredLocal myThredLocal = MyThredLocal.getInstance();
System.out.println(Thread.currentThread().getName() + "A:"
+ myThredLocal.getIndex());
}
}
class B {
public void getB() {
MyThredLocal myThredLocal = MyThredLocal.getInstance();
System.out.println(Thread.currentThread().getName() + "B:"
+ myThredLocal.getIndex());
}
}
运行结果为:
Thread-0A:21
Thread-1A:44
Thread-4A:57
Thread-3A:55
Thread-2A:23
Thread-3B:55
Thread-4B:57
Thread-1B:44
Thread-0B:21
Thread-2B:23
由此反应出 ThreadLocal 保证了同一线程内的变量共享。