当访问共享的可变数据时,通常需要使用同步,一种避免使用同步的方式就是不共享数据。Java提供了ThreadLocal类来方便开发者们实现线程封闭,在这个ThreadLocal类中的某个值与保存值的对象关联起来。ThreadlLocal提供了get与set方法,这些方法为每一个使用该变量的线程都存着一份独立的副本,因此get总是返回当前执行线程再调用set时设置的最新值。
package com.zy.charter3;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class ThreadLocalDemo {
public static void main(String[] args) {
SafeTask task = new SafeTask();
//
UnSafeTask task = new UnSafeTask();//可以试试这个
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(task);
thread.start();
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class UnSafeTask implements Runnable {
private Date startDate;
@Override public void run() {
startDate = new Date();
System.out.println("Start Thread:" + Thread.currentThread().getName() + "time:" + startDate);
try {
TimeUnit.SECONDS.sleep((int)Math.rint(Math.random()*10));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Thread finished:" + Thread.currentThread().getName() + "time:" + startDate);
}
}
class SafeTask implements Runnable {
private static ThreadLocal<Date> startDate = new ThreadLocal<Date>() {
protected Date initialValue() { return new Date(); }
};
@Override public void run() {
System.out.println("Start Thread:" + Thread.currentThread().getName() + "time:" + startDate.get());
try {
TimeUnit.SECONDS.sleep((int)Math.rint(Math.random()*10));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} System.out.println("Thread finished:" + Thread.currentThread().getName() + "time:" + startDate.get()); }}
这里面有两个demo,一个用了ThreadLocal,一个没用