`
yang_ch
  • 浏览: 79509 次
社区版块
存档分类
最新评论

线程池、ThreadLocal、Tomcat 应用小结

阅读更多

 

这两天遇到几个多线程的问题,多方找资料测试,现记录下测试结果,供自己以后查询用

 

遇到问题:

项目最近在考虑Rest化,第一个问题就是session管理,现考虑使用redis存储session,并对不需要创建session的接口调用中,使用threadLocal存储用户信息,在请求开始时,将用户信息存储到threadLocal中,第一个问题,user信息会乱掉。

解决过程如下:

1.经调试发现,有时候在设置用户信息之前ThreadLocal中就已经存在了值。

2.然后继续调试,打印出线程号,发现多次请求线程号是相同的,也就是说,N次请求是有可能是使用同一个线程。

3.然后考虑到Tomcat等web容器肯定是有线程池机制的,可能是线程池在搞鬼,查看ThreadLocal源码资料,ThreadLocal最终是绑定在当前的Thread上的,而使用线程池之后,线程执行结束,并不会销毁,而是放回线程池中,这样下次请求时,直接使用了池中的线程,节约线程创建和销毁的资源开销。这样也确实能解释我遇到的问题。

4.当然一切只是猜测,而且自己使用线程池去验证下,代码如下:

创建一个对象,用来测试线程的局部变量:

package com.ych.test;

public class TestObj {

	private int i;
	
	public TestObj(int i){
		this.i = i;
	}
	
	public void setI(int i) {
		this.i = i;
	}
	
	public int getI() {
		return i;
	}
}

 

创建线程,打印线程中的信息:

public class SaveThread extends Thread{
	
	private TestObj obj;
	
	private static ThreadLocal<TestObj> context = new ThreadLocal<TestObj>();
	
	public SaveThread(TestObj obj,String name){
		super(name);
		this.obj = obj;
	}

	@Override
	public void run() {
		try{
			if(context.get() == null){
				System.out.println("threadLocal中为null");
			}else{
				System.out.println("threadLocal中为:"+context.get().getI());
			}
			context.set(obj);
			System.out.println("thread name is " + Thread.currentThread().getName() + " id为:"+Thread.currentThread().getId()+",变量值:" +obj.getI());
			Thread.sleep(2000);
		}catch(InterruptedException ex){
			ex.printStackTrace();
		}
	}
}

 

main方法中执行,查看执行结果:

public class TestThread {

	private static Executor executor = Executors.newFixedThreadPool(2);
	public static void main(String[] args) {
		TestObj t1 = new TestObj(1);
		TestObj t2 = new TestObj(2);
		TestObj t3 = new TestObj(3);
		
		SaveThread s1 = new SaveThread(t1,"11");
		SaveThread s2 = new SaveThread(t2,"22");
		SaveThread s3 = new SaveThread(t3,"33");
		executor.execute(s1);
		executor.execute(s2);
		executor.execute(s3);
		
	}
}

 

 

测试结果:

threadLocal中为null
threadLocal中为null
thread name is pool-1-thread-2 id为:16,变量值:2
thread name is pool-1-thread-1 id为:15,变量值:1
threadLocal中为:1
thread name is pool-1-thread-1 id为:15,变量值:3

 

看来我的推测基本是正确的。

 

最后,解决办法很简单,在spring拦截器中postHandle中remove掉该信息即可。

 

注:现在还有一个问题困扰我,如果线程不被销毁,那其中的变量岂不是不会被GC回收?如果线程较多的话是否会产生内存泄漏,这个还需要其他方法验证

 

 

分享到:
评论

相关推荐

    ThreadLocal应用示例及理解

    以上就是关于ThreadLocal的基本概念、使用方法、生命周期管理和实际应用示例的详细解释。了解并熟练掌握ThreadLocal可以帮助我们编写出更高效、更安全的多线程代码。在Java并发编程中,ThreadLocal是一个不可或缺的...

    ThreadLocal垮线程池传递数据解决方案.docx

    "ThreadLocal垮线程池传递数据解决方案" ThreadLocal 是Java语言中的一种机制,旨在提供线程内数据的传递解决方案。然而,在实际生产中,线程一般不可能孤立的独立去运行,而是交给线程池去调度处理。这时,...

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

    - **难以调试**:由于ThreadLocal的隐式性,有时可能会导致难以发现的问题,特别是当线程池中的线程复用时。 ### 4. 使用注意事项 - 使用完毕后,应调用`remove()`方法清除ThreadLocal变量,防止内存泄漏。 - 尽量...

    运行在tomcat容器中的ThreadLocal容易产生的问题

    运行在tomcat容器中的ThreadLocal容易产生的问题ThreadLocal在tomcat容器中的的生命周期并不等于web request的生命周期,所以(以下讨论的是tomcat容器中使用ThreadLocal),所以ThreadLocal不应保存与请求会影响的...

    ThreadLocal 内存泄露的实例分析1

    而 Tomcat 中,每个请求都会创建新的线程来处理,这些线程在处理完请求后,通常不会立即终止,而是进入线程池等待下一次复用。因此,只要线程还在,`ThreadLocal` 中的 `MyCounter` 对象就不会被垃圾收集,也就意味...

    ThreadLocal源码以及应用.md

    ThreadLocal源码以及应用

    ThreadLocal

    ThreadLocal的一个经典应用场景是在数据库连接池中,每个线程都可以有自己的数据库连接,而无需在多个线程间共享,这样可以简化代码并提高性能。另外,它也可以用于HTTP请求上下文,存储请求相关的数据,如用户会话...

    ThreadLocal_ThreadLocal源码分析_

    4. **注意线程池中的ThreadLocal**:线程池中的线程可能会被重用,若不清理ThreadLocal,可能导致后续任务访问到错误的变量副本。 通过理解ThreadLocal的原理和最佳实践,我们可以更有效地利用它来解决多线程环境下...

    Java ThreadLocal类应用实战案例分析

    Java ThreadLocal类应用实战案例分析 Java ThreadLocal类是Java语言中的一种线程局部变量机制,允许每个线程都拥有自己的变量副本,从而避免了多线程之间的变量冲突。在本文中,我们将通过实战案例分析Java ...

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

    ThreadLocal的基本原理,核心机制,源码,ThreadLocal在分布式架构中的应用,ThreadLocal在基础架构,开源中间件,使用非常广泛,建议掌握。

    java 简单的ThreadLocal示例

    **ThreadLocal的应用场景:** 1. **线程安全的上下文:** ThreadLocal常用于保存线程上下文信息,如用户Session、数据库连接、事务ID等,确保这些信息只在当前线程内有效。 2. **避免同步:** 如果多个线程需要...

    tomcat中多线程对于servlet处理的4篇资料

    Tomcat允许通过添加自定义的Executor来替换默认的线程池,这样可以根据应用需求调整线程池的配置,例如设置更复杂的线程调度策略。 综上所述,理解Tomcat中的多线程处理对于优化Servlet性能和解决潜在的并发问题至...

    Java单线程ThreadLocal串值问题解决方案

    Java单线程ThreadLocal串值问题解决方案 Java单线程ThreadLocal串值问题解决方案主要介绍了Java单线程...本文通过示例代码,详细介绍了ThreadLocal的使用、问题出现和解决方法,并解释了Tomcat服务器的线程池机制。

    ThreadLocal.pdf

    ThreadLocal

    目前项目在用性能稳定的线程池源码

    1. 初始化:每个工作线程在启动时,可能会初始化一些线程局部变量,如ThreadLocal,以便在执行任务时保持独立的数据环境。 2. 执行任务:PooledThread会有一个run方法,该方法从工作队列中取出任务并执行。执行完毕...

    理解ThreadLocal

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

    threadLocal

    ThreadLocal是Java编程语言中的一个线程局部变量类,它为每个线程提供了一个独立的变量副本,使得每个线程可以独立地改变...通过阅读和理解这些资料,开发者可以深化对ThreadLocal的理解,并将其有效地应用于项目中。

    使用ThreadLocal管理“session”数据

    在Web应用中,特别是对于"session"数据的管理,ThreadLocal可以作为一种有效的解决方案。 1. **什么是Session?** Session是HTTP协议中的一个概念,用于存储用户在服务器端的状态信息。当用户登录网站后,服务器会...

    ThreadLocal整理.docx

    ThreadLocal 整理 ThreadLocal 是 Java 中的一个重要组件,它能够在每个线程中保持独立的副本。这个功能是通过 Thread 类中的 threadLocals 属性来实现的,这个属性实际上是一个 Entry 数组,其中的每个 Entry 都...

Global site tag (gtag.js) - Google Analytics