`

ThreadLocal3

阅读更多

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{
	 
}

 

0
0
分享到:
评论
1 楼 mercyblitz 2010-05-28  
Thread 没有生命周期时间,对于这种资源(需要关闭的),ThreadLocal还是会有问题。

相关推荐

    ThreadLocal应用示例及理解

    **线程局部变量(ThreadLocal)是Java编程中一个非常重要的工具类,它在多线程环境下提供了线程安全的数据存储。ThreadLocal并不是一个变量,而是一个类,它为每个线程都创建了一个独立的变量副本,使得每个线程都...

    ThreadLocal

    3. 在需要访问该变量的线程中,通过`get`方法获取变量副本。 4. 当不再需要使用ThreadLocal时,建议清除线程局部变量,防止内存泄漏。可以调用`remove`方法来实现。 ThreadLocal的一个经典应用场景是在数据库连接池...

    ThreadLocal 内存泄露的实例分析1

    在 `LeakingServlet` 的 `doGet` 方法中,如果 `ThreadLocal` 没有设置值,那么会创建一个新的 `MyCounter` 并设置到 `ThreadLocal` 中。关键在于,一旦 `MyCounter` 被设置到 `ThreadLocal`,那么它将与当前线程...

    正确理解ThreadLocal.pdf

    3. **日志记录**:在多线程环境中,`ThreadLocal`可以用于维护每个线程的日志上下文,如线程ID、用户名等,便于日志信息的记录和分析。 4. **性能优化**:在某些计算密集型应用中,`ThreadLocal`可以用于缓存线程...

    ThreadLocal整理.docx

    同时, ThreadLocal 还提供了扩容机制,当数组的 size 大于总长度的 2/3 时,会触发扩容操作,扩容后将原来的数组长度乘以 2倍。 在 ThreadLocal 中,set 方法的逻辑是先获取当前线程的存取副本变量的 map,然后...

    java 简单的ThreadLocal示例

    Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,尤其在处理线程间数据隔离和共享时。ThreadLocal不是线程本身,而是为每个线程提供一个独立的变量副本,使得每个线程都可以独立地改变...

    java事务 - threadlocal

    Java事务和ThreadLocal是两种在Java编程中至关重要的概念,它们分别用于处理多线程环境下的数据一致性问题和提供线程局部变量。 首先,我们来深入理解Java事务。在数据库操作中,事务是一系列操作的集合,这些操作...

    java中ThreadLocal详解

    ### Java中ThreadLocal详解 #### 一、ThreadLocal概述 在Java多线程编程中,`ThreadLocal`是一个非常重要的工具类,它提供了一种在每个线程内部存储线程私有实例的方法。通常情况下,当多个线程共享某个变量时,...

    ThreadLocal.pdf

    由于提供的文件内容包含了大量的OCR扫描错误和重复内容,我将尽力根据现有的信息,提供一个关于ThreadLocal的知识点总结。如果出现无法理解的片段,我会尝试根据上下文进行合理推断并忽略错误的部分。 在Java中,...

    ThreadLocal简单Demo

    3. **键值对**: 在`ThreadLocalMap`中,键是`ThreadLocal`对象的弱引用,而值是用户设置的对象。弱引用意味着,如果键不再被其他地方引用,即使值还在,垃圾收集器也会回收键,从而自动清理`ThreadLocalMap`中不再...

    理解ThreadLocal

    理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 理解ThreadLocal

    ThreadLocal的几种误区

    3. 存储数据库会话:在Spring Hibernate ORM中,ThreadLocal常用来保存数据库连接的Session,确保每个线程有自己的Session,避免线程间的资源冲突。 总之,ThreadLocal是一个强大的工具,但理解其工作原理和潜在...

    Android ThreadLocal实现原理

    3. **实际应用示例:Looper** 在 Android 中,`Looper` 类用于管理消息循环,通常在主线程中使用。`Looper` 内部也使用了 `ThreadLocal` 来存储与当前线程关联的 `Looper` 对象,这样就可以确保每个线程都有自己的...

    ThreadLocal原理及在多层架构中的应用

    ### 3. ThreadLocal的优缺点 优点: - **简单易用**:ThreadLocal提供了一种简单的线程间数据隔离的实现方式,代码简洁,无需复杂的同步机制。 - **性能提升**:避免了线程同步的开销,提高了程序执行效率。 缺点...

    设计模式及ThreadLocal资料

    本资料主要聚焦于两种设计模式以及Java中的ThreadLocal特性。 首先,我们来探讨单例模式。单例模式是一种确保一个类只有一个实例,并提供全局访问点的设计模式。在Java中,通常通过私有构造函数、静态工厂方法或...

    使用ThreadLocal管理“session”数据

    3. **如何使用ThreadLocal实现Session管理?** 首先,定义一个ThreadLocal变量来存储session对象: ```java public class SessionThreadLocal { public static final ThreadLocal&lt;Session&gt; SESSION_HOLDER = new...

    ThreadLocal_ThreadLocal源码分析_

    3. **谨慎使用全局ThreadLocal**:全局的ThreadLocal变量可能导致数据在不同线程间意外共享,应谨慎使用。 4. **注意线程池中的ThreadLocal**:线程池中的线程可能会被重用,若不清理ThreadLocal,可能导致后续任务...

    threadLocal

    3. 内存管理:了解Java的内存模型和垃圾回收机制,才能理解ThreadLocal的内存泄漏风险和弱引用的作用。 4. HTTP相关:虽然题目中没有直接涉及,但HTTPClient是一个常见的网络通信工具,经常和ThreadLocal结合使用,...

    事务的封装和Threadlocal实例

    private static final ThreadLocal&lt;Connection&gt; connectionHolder = new ThreadLocal(); public static void setConnection(Connection conn) { connectionHolder.set(conn); } public static Connection get...

Global site tag (gtag.js) - Google Analytics