实例一:
package com.thread;
public class ThreadLocalTest {
private static ThreadLocal<String> threadLocal = new ThreadLocal<String>();
public static class Thread1 extends Thread{
private String name;
public Thread1(String name){
this.name=name;
}
public void run(){
System.out.println(name+" 初始值:"+threadLocal.get());
threadLocal.set("V1");
System.out.println(name+" 设置后值:"+threadLocal.get());
}
}
public static class Thread2 extends Thread{
private String name;
public Thread2(String name){
this.name=name;
}
public void run(){
System.out.println(name+" 初始值:"+threadLocal.get());
threadLocal.set("V2");
System.out.println(name+" 设置后值:"+threadLocal.get());
}
}
public static void main(String[] args) {
threadLocal.set("main start");
System.out.println("主线程初始值:"+threadLocal.get());
new Thread1("T1线程").start();
new Thread2("T2线程").start();
}
}
----------------------------
主线程初始值:main start
T1线程 初始值:null
T1线程 设置后值:V1
T2线程 初始值:null
T2线程 设置后值:V2
实例二:
package com.thread;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class DateUtil {
private static ThreadLocal local = new ThreadLocal();
//对于固定格式的,本方法可以只生成一个SimpleDateFormat对象
// public static String format(Date date) {
// SimpleDateFormat formator = (SimpleDateFormat)local.get();
// if (formator == null) {
// formator = new SimpleDateFormat("yyMMddHHmmss");
// local.set(formator);
// }
// return formator.format(date);
// }
//对于格式化成不同格式的日期,一种格式一个SimpleDateFormat对象
public static String format(Date date,String DateForm) {
SimpleDateFormat formator = (SimpleDateFormat)local.get();
if (formator == null) {
formator = new SimpleDateFormat(DateForm);
local.set(formator);
}
return formator.format(date);
}
public static void main(String[] args) {
// System.out.println(DateUtil.format(Calendar.getInstance().getTime()));
// System.out.println(local.get());
// System.out.println(DateUtil.format(Calendar.getInstance().getTime())+1);
// System.out.println(local.get());
System.out.println(DateUtil.format(Calendar.getInstance().getTime(), "yyMMddHHmmss"));
System.out.println(local.get());
local.set(null);//若这边不设置下null,则程序前后输出的对象是同一个SimpleDateFormat对象
System.out.println(DateUtil.format(Calendar.getInstance().getTime(), "yyyy-MM-dd"));
System.out.println(local.get());
}
}
-------------------------
120925164039
java.text.SimpleDateFormat@d2a77a40
2012-09-25
java.text.SimpleDateFormat@f67a0200
实例三(hibernate session实现):
public class HibernateUtil {
public static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new Configuration().configure()
.buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static final ThreadLocal<Session> session =
new ThreadLocal<Session>();
public static Session currentSession() throws HibernateException {
Session s = session.get();
if(s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = session.get();
if(s != null) {
s.close();
}
session.set(null);
}
}
ThreadLocal与其它同步机制的比较:
ThreadLocal和其它同步机制相比有什么优势呢?ThreadLocal和其它所有的同步机制都是为了解决多线程中的对同一变量的访问冲突,在普通的同步机制中,是通过对象加锁来实现多个线程对同一变量的安全访问的。这时该变量是多个线程共享的,使用这种同步机制需要很细致地分析在什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放该对象的锁等等很多。所有这些都是因为多个线程共享了资源造成的。ThreadLocal就从另一个角度来解决多线程的并发访问,ThreadLocal会为每一个线程维护一个和该线程绑定的变量的副本,从而隔离了多个线程的数据,每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的整个变量封装进ThreadLocal,或者把该对象的特定于线程的状态封装进ThreadLocal。
当然ThreadLocal并不能替代同步机制,两者面向的问题领域不同。同步机制是为了同步多个线程对相同资源的并发访问,是为了多个线程之间进行通信的有效方式;而ThreadLocal是隔离多个线程的数据共享,从根本上就不在多个线程之间共享资源(变量),这样当然不需要对多个线程进行同步了。所以,如果你需要进行多个线程之间进行通信,则使用同步机制;如果需要隔离多个线程之间的共享冲突,可以使用ThreadLocal,这将极大地简化你的程序,使程序更加易读、简洁。