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 ...
随机推荐
- 【智能家居篇】wifi网络结构(上)
转载请注明出处:http://blog.csdn.net/Righthek 谢谢! WIFI是什么.相信大家都知道,这里就不作说明了. 我们须要做的是深入了解其工作原理,包含软硬件.网络结构等.先说明 ...
- lpad&rpad
lpad( string, padded_length, [ pad_string ] ) string: 准备被填充的字符串 padded_length: 填充之后的字符串长度 pad_string ...
- C++数值类型极限值的获取
C/C++中基本类型的数值极限值一般来说都是与详细平台有关的,在程序设计的过程中为了写出与平台无关的程序则必须通过合理科学的方法去获取各种类型的极值,经常使用的获取方法有两种:一种是传统的C语言所採用 ...
- 24岁菜鸟,能一个人撑起App开发吗
"疲惫吾心.怎样躲藏.四处荒芜,怎话忧伤?"临近中秋,看到艾瑞斯的QQ签名,无尽的伤感.这个年仅24的青年.连续3年没有回家了,近期一个月总是失眠,没有家人的陪伴,就连女朋友 ...
- centos下yum安装lamp和lnmp轻松搞定
centos下yum安装lamp和lnmp轻松搞定.究竟多轻松你看就知道了.妈妈再也不操心不会装lamp了. 非常辛苦整理的安装方法,会持续更新下去.凡无法安装的在评论里贴出问题来,会尽快解决.共同维 ...
- 分享:Android系统的经常使用权限整理
1.ACCES_NETWORK_STATE 同意应用程序获取网络状态信息的权限 2.ACCESS_WIFI_STATE 同意应用程序获取Wi-Fi网络状态的权限 3.BAT ...
- poj--3630--Phone List(字典树+前缀判断)
Phone List Time Limit: 1000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u Submit St ...
- java多线程 interrupt(), interrupted(), isInterrupted()方法区别
interrupt()方法: 作用是中断线程. 本线程中断自身是被允许的,且"中断标记"设置为true 其它线程调用本线程的interrupt()方法时,会通过checkAcces ...
- Centos6.5添加Epel和Remi源安装Lamp环境
想搭建一个Lamp环境,因为编译安装太麻烦,对于我这样的新手来说,太过于复杂.而CentOS自带的Apache.MySql和PHP的版本都太低,不想用.上百度搜了一轮,原来可以通过添加Epel和Rem ...
- linux中openssl生成证书和自签证书
1.首先要生成服务器端的私钥(key文件): 命令: openssl genrsa -des3 -out server.key 1024 运行时会提示输入密码,此密码用于加密key文件(参数des3便 ...