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--;
		 }
	 }
 }
执行结果:

Java ThreadLocal类学习的更多相关文章
- Java常用类学习笔记总结
		Java常用类 java.lang.String类的使用 1.概述 String:字符串,使用一对""引起来表示. 1.String声明为final的,不可被继承 2.String ... 
- ThreadLocal类学习笔记
		这个类在java1.2中就出现了,线程独有的变量(每个线程都有一份变量),使用它的好处之一就是可以少传许多参数. 在哪里用到它呢?有连接池的地方就有它的身影,连接池包括数据库连接池,网络连接池等. i ... 
- 学习笔记:因为java匿名类学习到接口的一些小用法
		在看CometD的示例代码时发现了许多有意思的代码,但说实话看别人的代码确实是件很累的事情,所以就看到这个知识点做一下记录吧. 先看一段代码: 代码1 这段代码中有一个new的操作,而且是在方 ... 
- java基础知识回顾之java Thread类学习(八)--java.util.concurrent.locks(JDK1.5)与synchronized异同讲解
		看API文档介绍几个方法: JDK1.5中提供了多线程的升级解决方案: 特点: 1.将同步synchronized显示的替换成Lock 2.接口Conditio ... 
- java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)
		*java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时 ... 
- java基础知识回顾之java Thread类学习(三)--java线程实现常见的两种方式实现好处:
		总结:实现Runnable接口比继承Thread类更有优势: 1.因为java只能单继承,实现Runnable接口可以避免单继承的局限性 2.继承Thread类,多个线程不能处理或者共享同一个资源,但 ... 
- Java Math类学习
		1. java.lang.Math Math类其成员皆为静态成员(static),无需创建对象,直接用类名Math作为前缀使用它们即可. 2. Math类有两个静态常量:E(自然对数)和PI(圆周 ... 
- java arrays类学习
		java.util.Arrays类能方便地操作数组,它提供的所有方法都是静态的. 具有以下功能: (1)给数组赋值:通过fill方法. (2)对数组排序:通过sort方法,按升序. (3)比较数组:通 ... 
- java工具类学习整理——集合
		好久没有总结一些东西了,同时集合部分的知识点也学习的比较早了,但是从来没有抽时间去研究和学习,今天正好有时间就总结一下map常用的遍历方法: package runningwhile; import ... 
随机推荐
- android   AppWidget的使用以及利用TimerTask实现widget的定时更新
			第一步:首先是Widget的定义声明: 在资源文件下的xml目录中建立文件example_appwidget_info.xml: <?xml version="1.0" en ... 
- COCOS学习笔记--Cocod2dx内存管理(三)-Coco2d-x内存执行原理
			通过上两篇博客.我们对Cocos引用计数和Ref类.PoolManager类以及AutoreleasePool类已有所了解,那么接下来就通过举栗子来进一步看看Coco2d-x内存执行原理是如何的. / ... 
- query.setFirstResult解析
			转自:https://blog.csdn.net/thinkingcao/article/details/78053622 
- Linux,Docker,Jenkins  No such file or directory
			你们先休息下,我先哭哭! 今天在做交接项目的bug修改的时候,在创建文件的时候报错 No such file or directory 然后跟着路径去linux中查看了该路径,但确实存在,并且权限都是 ... 
- 剑指offer——05用两个栈实现队列(Python3)
			思路:(转) 代码: # -*- coding:utf-8 -*-class Solution: stack1 = [] stack2 = [] def push(self, node): self. ... 
- 使用log4net记录日志到数据库(含自定义属性)
			日志输出自定义属性! 特来总结一下: 一.配置文件 使用log4写入数据库就不多说了,网上方法很多,自定义字段如下 <commandText value="INSERT INTO db ... 
- HDU 1575 矩阵快速幂裸题
			题意:中文题 我就不说了吧,... 思路:矩阵快速幂 // by SiriusRen #include <cstdio> #include <cstring> using na ... 
- mybatis通用的crud的接口
			http://git.oschina.net/jrl/mybatis-mapper https://www.oschina.net/p/mybatis-plus 
- Java NIO(一)概述
			说明 java NIO是从java1.4开始引入的一个新的IO API,它支持面向缓冲区,基于通道的IO操作,它的核心是通道(channel),缓冲区(buffer),选择器(selector) NI ... 
- Android DrawerLayout设置左右侧滑菜单为全屏
			我们可以在MainActivity中获取屏幕宽度后动态赋值给侧滑菜单. 在oncreate时 DisplayMetrics metric = new DisplayMetrics(); getWind ... 
