Java ThreadLocal类学习

ThreadLocal为线程局部变量,通过线程名(key)-对象(value)的Map来获取每个线程对应的对象。我们不能通过ThreadLocal处理多线程并发问题,但是每个线程可以通过ThreadLocal轻易的访问到自己保存的对象。

以Hibernate中sessionFactory,Session举例

	在Hibernate中sessionFactory是线程安全,在web应用中只要有一份实例就行,但是Session是每个线程都各自拥有一份实例,不然不同的线程持有同一个session对象进行CRUD,会引起数据操作混乱。因此为每一个线程都分配一个独自的Session实例,这里可以应用了ThreadLocal。下面进行简单模拟,说明ThreadLocal使用
//SessioinFactory类保存一个自定义的ThreadLocalSessionContext对象
package com.localthread;

public class SessionFactory {
	public ThreadLocalSessionContext sc;
	public SessionFactory(){
		sc= new ThreadLocalSessionContext(this);
	}
	public Session currentSession(){
		return sc.currentSession();
	}
	public Session createSession(){
		return new Session();
	}
}

package com.localthread;

import java.util.HashMap;
import java.util.Map;
//使用ThreadLocal来保存一个以SessionFactory-Session为key-value的Map。
public class ThreadLocalSessionContext {
	private SessionFactory sessionFactory;
	public ThreadLocalSessionContext(SessionFactory sessionFactory){this.sessionFactory=sessionFactory;}
	public SessionFactory factory(){return sessionFactory;}
	private static final ThreadLocal<Map> CONTEXT_TL=new ThreadLocal();//应用ThreadLocal,其中的Map的SessionFactory(key)-Session(value)
	//获得当前线程的Session,没有则用SessioinFactory创建一个
	public final Session currentSession(){
		Session session=exsitSession(factory());
		if(session==null){
			 session=factory().createSession();
			bind(factory(),session);
		}	
		return session;
	}
	public static Map sessionMap(){
		return CONTEXT_TL.get();
	}
	public static Session exsitSession(SessionFactory factory){
		Map sessionMap=sessionMap();
		if(sessionMap==null)
			return null;
		return (Session) sessionMap.get(factory);
	}
	public static void bind(SessionFactory factory,Session session){
		Map sessionMap=sessionMap();
		if(sessionMap==null){
			sessionMap=new HashMap();
			CONTEXT_TL.set(sessionMap);
		}
			
		sessionMap.put(factory, session);
	}
}
package com.localthread;
//打印sessionId
public class Session {
	public int sessionId=0;
	public void print(){
		System.out.println(Thread.currentThread().getName()+":"+this+",sessionId:"+sessionId++);
	}
}
//测试类
/***

启动三个线程共享一个SessionFactory,在每个线程的Run方法中获得每个线程各自对应的Session,测试输出如下图:
其中SessionId++按照预期运行。
**/
package com.localthread;

public class Main {
	public static void main(String[] args) {
		SessionFactory factory=new SessionFactory();
		SessionThread s1=new SessionThread(factory);
		SessionThread s2=new SessionThread(factory);
		SessionThread s3=new SessionThread(factory);
		s1.start();s2.start();s3.start();
	}
}
 class SessionThread extends Thread{
	 private int count=5;
	 private SessionFactory factory;
	 public SessionThread(SessionFactory factory){
		 this.factory=factory;
	 }
	 public void run(){
		 while(count>0){
			 factory.currentSession().print();
			 count--;
		 }
	 }
 }

执行结果:

posted @   不被女生喜欢好多年  阅读(195)  评论(0编辑  收藏  举报
编辑推荐:
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
阅读排行:
· 2025成都.NET开发者Connect圆满结束
· 后端思维之高并发处理方案
· 千万级大表的优化技巧
· 在 VS Code 中,一键安装 MCP Server!
· 10年+ .NET Coder 心语 ── 继承的思维:从思维模式到架构设计的深度解析
点击右上角即可分享
微信分享提示