`

通过代码,了解ThreadLocal

 
阅读更多

在看此代码时,先看http://www.iteye.com/topic/103804 

如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。  

 

 

 

package test1;

import java.util.Random;


/**
 * 2个线程,生成数据后,放入各自的线程中,使其他线程无法访问到。
 * @author Administrator
 *
 */
public class ThreadLocalTest {
	public static void main(String[] args) {
		new ThreadLocalTest().init();
	}
	
	private void init() {
		for (int i = 0; i < 2; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					int data = new Random().nextInt();
					System.out.println("当前线程:" + Thread.currentThread().getName() + "  数据:" + data);
					
					MyObj obj = MyObj.getThreadInstance();
					obj.setAge(data);
					obj.setName("name" + data);
					
					new A().getData();
					new B().getData();
				}
			}){}.start();
		}
	}

	
	class A {
		public void getData () {
			MyObj obj = MyObj.getThreadInstance();
			System.out.println("A: 当前线程:" + Thread.currentThread().getName() + "  数据:" + obj.toString());
		}
	}
	
	class B {
		public void getData () {
			MyObj obj = MyObj.getThreadInstance();
			System.out.println("B: 当前线程:" + Thread.currentThread().getName() + "  数据:" + obj.toString());
		}
	}
	
	
}


class MyObj {
	private MyObj(){};
	
	private static ThreadLocal<MyObj> map = new ThreadLocal<MyObj>();
	
	
	/*
	 * 必须加synchronized(张孝祥老师说此处不需加synchronized是错误的)
	 * 如不加:线程0进入,发现instance为null,刚要实例化时,cpu给了线程1,线程1实例化完instance,
	 * 刚要返回,cpu给了线程0,线程0此时并未实例化instance,但发现已经实例化了,所以不再走map.set()方法,
	 * 导致MyObj obj = MyObj.getThreadInstance(); 从map中取出当前线程的instance为null
	 */
	public static synchronized MyObj getThreadInstance() {
		instance = map.get();
		if (instance == null) {
			instance = new MyObj();
			map.set(instance);
		}
		return instance;
	}
	
	private static MyObj instance;
	
	private int age;
	
	private String name;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String toString() {
		String str = String.format("名字: [%s], 年龄: [%d]", this.name, this.age);
		return str;
	}
	
	
	
}

 

 

分享到:
评论

相关推荐

    ThreadLocal,你真的了解吗?

    1.ThreadLocal的相关面试题 1)Java中的引用类型有哪几种? 2)每种引用类型的特点? 3)每种引用类型的场景是什么...Java中提供这四种引用类型主要有两个目的:第一是可以让程序员通过代码的方式决定某些对象的生命周

    深入理解ThreadLocal工作原理及使用示例

    主要介绍了深入理解ThreadLocal工作原理及使用示例,涉及ThreadLocal&lt;T&gt; 简介和使用示例及ThreadLocal的原理等相关内容,具有一定参考价值,需要的朋友可以了解下。

    day020-继承加强和设计模式代码和笔记.rar

    step4:在我们代码中通过创建对象或者类名的方式使用即可 3.2 使用自己的jar包 (造轮子) step1:选中自己想要封装成jar包的类,右键export导出 在输入框中输入 jar: 1. jar File : 普通...

    学生管理系统.rar

    使用三层架构改写我之前上传的代码 技术要点:1.面向接口编程2.使用工厂+接口进行对象的创建,降低层与层之间的耦合度,实现解耦合3.添加事务操作4.通过代理添加事务功能5.使用事务管理器6.使用ThreadLocal管理...

    Spring中文帮助文档

    3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. The ...

    Spring API

    3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. The ...

    spring chm文档

    3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. ...

    Spring 2.0 开发参考手册

    3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. ...

    Spring-Reference_zh_CN(Spring中文参考手册)

    7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动代理(autoproxy)”功能 7.9.1. 自动代理bean定义 7.9.1.1. BeanNameAutoProxyCreator 7.9.1.2. DefaultAdvisorAutoProxyCreator ...

Global site tag (gtag.js) - Google Analytics