CurrentThread.map.set(currentThreadLocal, myobject);
myobject = (MyObject) CurrentThread.map.get(currentThreadLocal);
总之要ThreadLocal正常工作的话,必须要
每个Thread都有自己的myobject,否则还是不能正确实现的!!
和同步完全没有关系啊! 同步从同到尾巴,所有的线程只有一个object做为value
ThreadLocal是每个线程都有一个object做为value
ThreadUniqueID.Hashmap.put(ThreadLocal, new object in each Thread);
通常的HaspMap
Hashmap.put( String ,object);
Hashmap.put( Integer ,object);
这样的KEY(String ,Integer)在不同线程中HASH以后也都是一样的,所以会混乱.
ThreadLocal做的就是让这个map本身在不同线程下是不同,同一线程相同.
在所有线程中 从头到尾只有一个ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>()
* Thread对象是JMV自动创建的
* ThreadLocal保存所有的Treads ,每一个Thread对应一个haspMap(key:threadlocal本身,value:要保存的数据)
*
* 奇妙的就是ThreadLocal保存乐所有线程的信息,利用乐这些信息.
* 当然只有我们调用get/set方法的时候才会去检查,如果ThreadLocal中没有当前Thread对应的map.就会 根据这个thread建立对应的map (initValue -projected 方法,重写)
也可以说,1个ThreadLocal对象,当前有4个线程,则1个ThreadLocal对象维护(可以,不是一定(当线程调用GET/SET的时候,注意是线程调用.每个线程第一次调用,会产生对应的线程MAP))4个线程对应的map.
class ThreadLocal{
Thread[] // JVM产生的线程数组而已
}
class Thread{
Map map (threadLocal,value);
}
我们可以用ThreadLocal保存Request,和同步没有任何关系,本身多线程下,每个请求都有不同的request对象!!
我们只是保存一下而已,方便取用.但是如果在DAO层等,用这种方法取用request,会让测试变的困难(需要虚拟request对象测试service ,dao....)
下面的代码乱写的,唉,水平太差
package a;
public class ThreadLocal5 {
/*
* 这个相当于一个容器
*/
public static void main(String... args) {
/*
* 一个容器只有一个Servlet实例 ServletServletTest 单实例多线程
*/
Servlet servletTest = new ServletTest();
/*
* 多个线程调用同一个servlet
*/
for (int i = 0; i < 4; i++) {
DummyThread dummyThread = new DummyThread(servletTest);
Thread thread = new Thread(dummyThread);
thread.start();
}
}
/*
* 打印信息而已
*/
public static void logWithThreadInFor(Object o) {
System.out.println(Thread.currentThread().getName() + " "
+ (null == o ? "null" : o.toString()));
}
}
/*
* 更好的ServletTest可以实现一个接口 DummyThread.callServlet() 调用接口方法
*/
class ServletTest implements Servlet {
/*
* servlet有一个dao实例变量 这个dao导致了多线程调用servlet不安全
*
* 除去这个dao,servlet是线程安全的
*/
private DAOTest dao = new DAOTest();
public void service() {
/*
* 方法内部定义的dao,不存在线程同步问题.会有很多实例,创建很多DAO
*/
//DAOTest dao = new DAOTest();
ThreadLocal5.logWithThreadInFor("Servlet: " + this.hashCode());
ThreadLocal5.logWithThreadInFor(" Dao: " + dao.hashCode());
/*
* 如果只有一个DAO,我们可以在DAO方法中每次都new Connection(),这样的话
* 同一个线程两个方法都是线程安全的,但是我们发现,在每一个线程中,DAO的不同方法,拿到的connection竟然是不同的,很郁闷
* 1个DAO = 多个线程 ; 每个线程 的每个DAO方法有一个CONNECTION
*/
dao.findUserIDByConnection(1);
dao.findUserIDByConnection2(2);
}
// init()
// destory()
// service
}
/*
* 这个DAOTest不是线程安全的 但是显然如果DAOTest的方法不调用任何实例变量,那么该方法是安全的
*/
class DAOTest {
/*
* 这样定义Connection是不安全的
* 所有线程的Connection是一样的,同一个对象
*/
MultipleConnection conn=MultipleConnection.getConnection();
/*
* 利用ThreadLocal,为每个线程建立一个Connection对象
*/
ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>(){
/*
*
* 每次返回的都是一个新的MultipleConnection.getConnection()
* 该方法在get的时候,如果ThreadLocal的map没有对应的值,就要执行
* 也就是说对每个线程只执行一次
* 不同线程得到不同的Connection,同个线程相同(DAO两个方法得到的CONNECTION是一样的)
*
* 也就是我们说的,一个DAO = 多个线程 = 多个connection,每个线程只有一个connection
* 把不安全的DAO,变成安全的== 针对connection来说
* (如果还有其他的实例变量...又不安全了)
*/
@Override
public MultipleConnection initialValue(){
//ThreadLocal5.logWithThreadInFor(" intial value");
return MultipleConnection.getConnection();
}
/*
* SingleConnection,单例模式
* 所以说尽管我用了ThreadLocal,其实没有用的!!
* 还是一个DAO = 多线程 = 一个connection
* 所有线程还是共享一个connection!!!
*/
/*@Override
public SingleConnection initialValue(){
//ThreadLocal5.logWithThreadInFor(" intial value");
return SingleConnection.getConnection();
}*/
} ;
public DAOTest(){
//ThreadLocal5.logWithThreadInFor("DAOTest Intial "); // main thread??
//intial();
}
private void intial(){
this.threadLocal.set(MultipleConnection.getConnection());
}
/*
* 这个方法线程是安全的
*/
public int findUserID(int id) {
return id;
}
public int findUserIDByConnection(int id) {
/*
* 定义在这里,可以让conn变的线程安全
*/
//conn=Connection.getConnection();
//
ThreadLocal5.logWithThreadInFor(" Connection: "+id+" "+conn.hashCode());
ThreadLocal5.logWithThreadInFor(" ThreadLocal Connection: "+"1"+" "+threadLocal.get().hashCode());
ThreadLocal5.logWithThreadInFor(" ThreadLocal Object =" +threadLocal);
return id;
}
public int findUserIDByConnection2(int id) {
/*
*定义在这里, 可以让conn变的线程安全
*/
//conn=Connection.getConnection();
//
ThreadLocal5.logWithThreadInFor(" Connection: "+id+" "+conn.hashCode());
ThreadLocal5.logWithThreadInFor(" ThreadLocal Connection: "+"2"+" "+threadLocal.get().hashCode());
/*
* 从头到尾只有一个ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>()
* Thread对象是JMV自动创建的
* ThreadLocal保存所有的Treads ,每一个Thread对应一个haspMap(key:threadlocal本身,value:要保存的数据)
*
* 奇妙的就是ThreadLocal保存乐所有线程的信息,利用乐这些信息.
* 当然只有我们调用get/set方法的时候才会根据这个thread建立对应的map
*
*/
ThreadLocal5.logWithThreadInFor(" ThreadLocal Object = " +threadLocal);
return id;
}
}
class DummyThread implements Runnable {
private Servlet servletTest = null;
public DummyThread(Servlet ServletTest) {
this.servletTest = ServletTest;
}
public void run() {
servletTest.service();
}
}
interface Servlet {
/*
* 可以传递过来request,response参数
*/
void service();
}
/* * 单例 这里仅仅是保证返回ServletTest
* 同时要把ServletTest的构造函数设置成私有. !!错误,这里怎么可以new呢?
* 内部类实现吧,非本文重点
* */
//==================
/*final class ServletManager {
private static final Servlet servlet = new ServletTest();
private ServletManager() {
}
public static Servlet getServlet() {
return servlet;
}
}*/
/*
*
* 每次返回的都是一个新的Connection
*
*/
class MultipleConnection implements Connection{
private MultipleConnection (){};
public static MultipleConnection getConnection() {
return new MultipleConnection();
}
}
class SingleConnection implements Connection{
/*
* 单例
*/
private static SingleConnection singleConnection = new SingleConnection ();
private SingleConnection(){};
public static SingleConnection getConnection() {
return singleConnection;
}
}
interface Connection{
}
分享到:
相关推荐
ThreadLocal应用示例及理解,这个写了相关的示例,可以参考一下。
ThreadLocal入门教程。 讲解了线程安全和ThreadLocal的使用的基本知识。
ThreadLocal
理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 理解ThreadLocal
学习ThreadLocal,了解其中的原理,以及学习其中的优点!避免坑点!!
正确理解ThreadLocal.pdf
java 简单的ThreadLocal示例
DbUTils中用ThreadLocal类
ThreadLocal的几种误区ThreadLocal的几种误区ThreadLocal的几种误区
主要介绍ThreadLocal的原理,实例分析以及注意事项
详解java底层实现原理,ThreadLocal底层实现的数据结构,为什么不会导致内存泄露
本例以序列号生成的程序为例,展示ThreadLocal的使用
ThreadLocal保证一个类的实例变量在各个线程中都有一份单独的拷贝, 从而不会影响其他线程中的实例变量
JDBC事务的封装和Threadlocal实例,参考博客:http://blog.csdn.net/daijin888888/article/details/50988053
设计模式及ThreadLocal详细讲解资料,想要学习java或者提升自己技术的同学可以下载观看
ThreadLocal源码分析,主要有ThreadLocal源码以及ThreadLocal的内部结构在jdk8前后的变化
Synchronized与ThreadLocal
ThreadLocal的基本原理,核心机制,源码,ThreadLocal在分布式架构中的应用,ThreadLocal在基础架构,开源中间件,使用非常广泛,建议掌握。
ThreadLocal原理及在多层架构中的应用