深入解析ThreadLocal
来源:互联网 发布:mac西柚色口红 编辑:程序博客网 时间:2024/04/28 03:45
1. ThreadLocal介绍
在Java中,ThreadLocal是摆脱不易变类实现线程安全的另一种方式。如果你用Java写过多线程或是并发的代码,你必定熟悉synchronization 或是Locking极大影响系统的可扩展性的高昂代价,然而你除了使用synchronization为多线程中分享对象别无选择。ThreadLocal为Java提供了另一种方式完成线程安全,它没有解决同步的需要,取而代之是通过提供给每个线程具体独立的变量副本来消除共享。其结果能够提高程序的可扩展性以及性能的提升。在类中,ThreadLocal实例是典型静态域,用于关联到一个线程的状态(比如用户ID 或者事物ID)。一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。由于Java中编写线程局部变量的代码相对其它语言(比如, FORTRAN)来说要笨拙一些,造成线程局部变量对于Java程序员来说不是那么熟悉。
例如,如下类对每个线程产生独一无二的本地标识。一个线程调用UniqueThreadIdGenerator.getCurrentThreadId()时它的ID被赋值,在它的序列调用中保持不变。只用线程处于活跃状态,ThreadLocal实例就能够访问。当线程消亡,线程对应的线程变量副本就会被垃圾回收。
import java.util.concurrent.atomic.AtomicInteger; public class UniqueThreadIdGenerator { private static final AtomicInteger uniqueId = new AtomicInteger(0); private static final ThreadLocal < Integer > uniqueNum = new ThreadLocal < Integer > () { @Override protected Integer initialValue() { return uniqueId.getAndIncrement(); } }; public static int getCurrentThreadId() { return uniqueId.get(); } } // UniqueThreadIdGenerator
2. ThreadLocal的应用
- ThreadLocal实现每个线程单例(Thread Singleton)或是像事务ID一样的每个线程上下文(Context)信息,这种实现特别棒。
- 能够将线程不安全的独享放到ThreadLocal中,这个线程安全的对象就会突然变得线程安全。
- ThreadLocal提供了另一种方式来扩展线程。通过ThreadLocal,你可以保护或是承载信息从一个方法到另一个你能够承载的方法。你没有必要去修改任何方法就能实现你所需要的功能,拥有了极大的可扩展性。
public class IContext { private String transactionId = null; public String getTransactionId() { return transactionId; } public void setTransactionId(String transactionId) { this.transactionId = transactionId; }}IThreadLocal类包含ThreadLocal对象实例set/get操作。
public class IThreadLocal { public static final ThreadLocal myThreadLocal = new ThreadLocal(); public static void set(IContext context){ myThreadLocal.set(context); } public static void remove(IContext context){ myThreadLocal.remove(); } public static IContext get(){ return (IContext)myThreadLocal.get(); }}
定义具体的业务处理逻辑,如下IBusinessSerive.java所示。
public class IBusinessService { Logger logger = LoggerFactory.getLogger(IBusinessService.class); public void callService(){ IContext myContext = IThreadLocal.get(); logger.info("current transaction ID :"+ myContext.getTransactionId()); }}使用线程测试上面定义的所有类。
public class ThreadLocalMain extends Thread{ @Override public void run(){ IContext context = new IContext(); context.setTransactionId("threadName: "+getName()+ ", id:" + getId()+", priority:" + getPriority() ); IThreadLocal.set(context); new IBusinessService().callService(); IThreadLocal.remove(context); } public static void main(String []args){ Thread threadOne = new ThreadLocalMain(); threadOne.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Thread threadTwo = new ThreadLocalMain(); threadTwo.start(); }}
结果如下:
Connected to the target VM, address: '127.0.0.1:3004', transport: 'socket'2013-04-26 22:18:20,613 INFO (org.java.IBusinessService:14) - current transaction ID :threadName: Thread-0, id:12, priority:5Disconnected from the target VM, address: '127.0.0.1:3004', transport: 'socket'2013-04-26 22:18:21,320 INFO (org.java.IBusinessService:14) - current transaction ID :threadName: Thread-1, id:13, priority:5
3. ThreadLocal在JavaEE中的应用
- 一个service方法中只有单个dao操作且此操作是一个select类的操作,请使用openSession,并且即时在finally块中关闭它;
- 如果一个service方法中涉及到多个dao操作,请一定使用getCurrentSession;
- 如果一个service方法中混合着select操作,delete, update, insert操作。请按照下述原则:
c. 忌讳,把select类的操作放在“事务”中;
4. openSession与getCurrentSession的区别
a. openSession一旦被调用,必须且一定要在finally块中close,要不然你就等着out of memory吧;
b. 如果你使用的是getCurrentSession,那么你不能在finally块中调用”session.close()”,不行你可以在finally块中用try-catch把session.close();包起来,然后在catch{}块中抛出这个exception,这个exception将会是:sessionhas been already closed。其原因是你用的是getCurrentSession,那么它在session.commit()或者是session.rollback()时就已经调用了一次session.close()了,因此你只要正确放置session.commit()与rollback()即可。另外,你可以在finally块中调用”ThreadLocalSessionContext.unbind(factory);”,以使得当前的事务结束时把session(即dbconnection)还回db connection pool中。
- 深入解析ThreadLocal
- java ThreadLocal深入解析
- android ThreadLocal 深入解析
- 深入解析ThreadLocal类
- ThreadLocal深入解析
- ThreadLocal深入
- 深入ThreadLocal
- 解析ThreadLocal
- ThreadLocal解析
- 解析ThreadLocal
- ThreadLocal解析
- ThreadLocal解析
- ThreadLocal解析
- ThreadLocal解析
- 解析ThreadLocal
- ThreadLocal解析
- 深入理解ThreadLocal
- ThreadLocal 深入了解
- 13 款开源的全文检索引擎
- 大数计算_乘法
- 放棋子--蓝桥杯
- Eclipse启动参数大全
- 大数计算_除法
- 深入解析ThreadLocal
- Windows下免安装Tomcat的配置
- 如何在MyEclipse中显示行数
- kill的用法
- 回文字符串啊~---太搞了 少年 DXH
- Java模拟容器的迭代器(Iterator模式)
- 同色三角形——解题报告
- 宏定义中的#,##
- linux下配置jdk