java threadlocal用法_Java ThreadLocal的使用

1.ThreadLocal用来解决多线程程序的并发问题

2.ThreadLocal并不是一个Thread,而是Thread的局部变量,当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每个线程都

可以独立地改变自己的副本,而不会影响其它线程所对应的副本.

3.从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思。

4.线程局部变量并不是Java的新发明,Java没有提供在语言级支持(语法上),而是变相地通过ThreadLocal的类提供支持.

5.ThreadLocal类中的方法:(JDK5版本之后支持泛型)

void set(T value)

将此线程局部变量的当前线程副本中的值设置为指定值

void remove()

移除此线程局部变量当前线程的值

protected T initialValue()

返回此线程局部变量的当前线程的“初始值”

T get()

返回此线程局部变量的当前线程副本中的值

6.ThreadLocal的原理:

ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素

的键为线程对象,而值对应线程的变量副本

7.自己模拟ThreadLocal:

public classSimpleThreadLocal{private Map valueMap=Collections.synchronizedMap(newHashMap());public voidset(Object newValue){

valueMap.put(Thread.currentThread(),newValue);//键为线程对象,值为本线程的变量副本

}publicObject get(){

Thread currentThread=Thread.currentThread();

Object o=valueMap.get(currentThread);//返回本线程对应的变量

if(o==null&&!valueMap.containsKey(currentThread)){//如果在Map中不存在,放到Map中保存起来

o=initialValue();

valueMap.put(currentThread,o);

}returno;

}public voidremove(){

valueMap.remove(Thread.currentThread());

}public voidinitialValue(){return null;

}

}

8.使用ThreadLocal的具体例子:

public classSequenceNumber{//通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值

private static ThreadLocal seNum=new ThreadLocal(){protectedInteger initialValue(){return 0;

}

}publicInteger getNextNum(){

seNum.set(seNum.get()+1);returnseNum.get();

}public static voidmain(String[] args){

SequenceNumber sn=newSequenceNumber();//3个线程共享sn,各自产生序列号

TestClient t1 = newTestClient(sn);

TestClient t2= newTestClient(sn);

TestClient t3= newTestClient(sn);

t1.start();

t2.start();

t3.start();

}private static class TestClient extendsThread{privateSequenceNumber sn;publicTestClient(SequenceNumber sn){this.sn=sn;

}public voidrun(){//每个线程打印3个序列号

for(int i=0;i<3;i++){

System.out.println("thread["+Thread.currentThread().getName()+",sn["+sn.getNextNum()+"]");

}

}

}

}

9.下面是一个完整的可执行的ThreadLocal例子:

public classThreadLocalExample {public static class MyRunnable implementsRunnable {private ThreadLocal threadLocal = newThreadLocal();

@Overridepublic voidrun() {

threadLocal.set((int) (Math.random() *100D));try{

Thread.sleep(2000);

}catch(InterruptedException e) {

}

System.out.println(threadLocal.get());

}

}public static voidmain(String[] args) {

MyRunnable sharedRunnableInstance= newMyRunnable();

Thread thread1= newThread(sharedRunnableInstance);

Thread thread2= newThread(sharedRunnableInstance);

thread1.start();

thread2.start();

}

}

上面的例子创建了一个MyRunnable实例,并将该实例作为参数传递给两个线程。两个线程分别执行run()方法,并且都在ThreadLocal实例上保存了不同的值。如果它们访问的不是ThreadLocal对象并且调用的set()方法被同步了,则第二个线程会覆盖掉第一个线程设置的值。但是,由于它们访问的是一个ThreadLocal对象,因此这两个线程都无法看到对方保存的值。也就是说,它们存取的是两个不同的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值