java 中ThreadLocal 的正确用法
java 中threadlocal 的正确用法
用法一:在关联数据类中创建private static threadlocalthrealocal的jdk文档中说明:threadlocal instances are typically private static fields in classes that wish to associate state with a thread。如果我们希望通过某个类将状态(例如用户id、事务id)与线程关联起来,那么通常在这个类中定义private static类型的threadlocal 实例。
例如,在下面的类中,私有静态 threadlocal 实例(serialnum)为调用该类的静态 serialnum.get() 方法的每个线程维护了一个“序列号”,该方法将返回当前线程的序列号。(线程的序列号是在第一次调用 serialnum.get() 时分配的,并在后续调用中不会更改。)
public class serialnum { // the next serial number to be assigned private static int nextserialnum = 0; private static threadlocal serialnum = new threadlocal() { protected synchronized object initialvalue() { return new integer(nextserialnum++); } }; public static int get() { return ((integer) (serialnum.get())).intvalue(); } }
【例】
public class threadcontext { private string userid; private long transactionid; private static threadlocal threadlocal = new threadlocal(){ @override protected threadcontext initialvalue() { return new threadcontext(); } }; public static threadcontext get() { return threadlocal.get(); } public string getuserid() { return userid; } public void setuserid(string userid) { this.userid = userid; } public long gettransactionid() { return transactionid; } public void settransactionid(long transactionid) { this.transactionid = transactionid; } }
用法二:在util类中创建threadlocal
这是上面用法的扩展,即把threadlocal的创建放到工具类中。
【例】例如hibernate的工具类:
public class hibernateutil { private static log log = logfactory.getlog(hibernateutil.class); private static final sessionfactory sessionfactory; //定义sessionfactory static { try { // 通过默认配置文件hibernate.cfg.xml创建sessionfactory sessionfactory = new configuration().configure().buildsessionfactory(); } catch (throwable ex) { log.error("初始化sessionfactory失败!", ex); throw new exceptionininitializererror(ex); } } //创建线程局部变量session,用来保存hibernate的session public static final threadlocal session = new threadlocal(); /** * 获取当前线程中的session * @return session * @throws hibernateexception */ public static session currentsession() throws hibernateexception { session s = (session) session.get(); // 如果session还没有打开,则新开一个session if (s == null) { s = sessionfactory.opensession(); session.set(s); //将新开的session保存到线程局部变量中 } return s; } public static void closesession() throws hibernateexception { //获取线程局部变量,并强制转换为session类型 session s = (session) session.get(); session.set(null); if (s != null) s.close(); } }
用法三:在runnable中创建threadlocal
还有一种用法是在线程类内部创建threadlocal,基本步骤如下:
1、在多线程的类(如threaddemo类)中,创建一个threadlocal对象threadxxx,用来保存线程间需要隔离处理的对象xxx。
2、在threaddemo类中,创建一个获取要隔离访问的数据的方法getxxx(),在方法中判断,若threadlocal对象为null时候,应该new()一个隔离访问类型的对象,并强制转换为要应用的类型。
3、在threaddemo类的run()方法中,通过调用getxxx()方法获取要操作的数据,这样可以保证每个线程对应一个数据对象,在任何时刻都操作的是这个对象。
public class threadlocaltest implements runnable{ threadlocal<studen> studenthreadlocal = new threadlocal<studen>(); @override public void run() { string currentthreadname = thread.currentthread().getname(); system.out.println(currentthreadname + " is running..."); random random = new random(); int age = random.nextint(100); system.out.println(currentthreadname + " is set age: " + age); studen studen = getstudent(); //通过这个方法,为每个线程都独立的new一个student对象,每个线程的的student对象都可以设置不同的值 studen.setage(age); system.out.println(currentthreadname + " is first get age: " + studen.getage()); try { thread.sleep(500); } catch (interruptedexception e) { e.printstacktrace(); } system.out.println( currentthreadname + " is second get age: " + studen.getage()); } private studen getstudent() { studen studen = studenthreadlocal.get(); if (null == studen) { studen = new studen(); studenthreadlocal.set(studen); } return studen; } public static void main(string[] args) { threadlocaltest t = new threadlocaltest(); thread t1 = new thread(t,"thread a"); thread t2 = new thread(t,"thread b"); t1.start(); t2.start(); } } class studen{ int age; public int getage() { return age; } public void setage(int age) { this.age = age; } }
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!