ThreadLocal实现线程级上下文
一.ThreadLocal测试
package com.junge.threadlocal.context; /**
* @author Administrator
*
*/
public class ThreadScopeData {
private ThreadScopeData() { } private static ThreadLocal<ThreadScopeData> threadLocal = new ThreadLocal<ThreadScopeData>(); public static ThreadScopeData getInstance() {
if (null == threadLocal.get()) {
threadLocal.set(new ThreadScopeData());
} return threadLocal.get();
} public static void main(String[] args) { new Thread(new Runnable() {
@Override
public void run() {
System.out.println(ThreadScopeData.getInstance()); }
}).start(); new Thread(new Runnable() {
@Override
public void run() {
System.out.println(ThreadScopeData.getInstance()); }
}).start();
}
}
二.对上下接口进行封装,使用方便(线程绑定不同的业务数据,线程之间的业务数据放在上下文中)
1.上下文接口ThreadContext
package com.junge.threadlocal.context; import java.util.Map; /**
* 线程上下文接口
*
* @author Administrator
*
*/
public interface ThreadContext { /**
* 保持用户名
*
* @param userName
*/
void setUserName(String userName); /**
* 获取用户名
*
* @return
*/
String getUserName(); /**
* 保持参数1
*
* @param param
*/
void setParam1(Object param); /**
* 获取参数1
*
* @return
*/
Object getParam1(); /**
* 添加参数
*
* @param key
* @param param
*/
void addParam(String key, Object param); /**
* 获取参数
*
* @param key
* @return
*/
Object getParam(String key); /**
* 获取所有添加的参数
*
* @return
*/
Map<String, Object> getAllParam();
}
2.线程上下文接口实现ThreadContextImpl
package com.junge.threadlocal.context; import java.util.HashMap;
import java.util.Map; /**
* 线程上下文接口实现
*
* @author Administrator
*
*/
public class ThreadContextImpl implements ThreadContext { private String userName; private Object param1; private Map<String, Object> paramMap; @Override
public void setUserName(String userName) {
this.userName = userName; } @Override
public String getUserName() { return this.userName;
} @Override
public void setParam1(Object param) {
this.param1 = param; } @Override
public Object getParam1() { return param1;
} /*
* (non-Javadoc)
*
* @see
* com.junge.threadlocal.context.ThreadContext#addParam(java.lang.String,
* java.lang.Object)
*/
@Override
public void addParam(String key, Object param) {
if (null == paramMap) {
paramMap = new HashMap<String, Object>();
} paramMap.put(key, param); } /*
* (non-Javadoc)
*
* @see
* com.junge.threadlocal.context.ThreadContext#getParam(java.lang.String)
*/
@Override
public Object getParam(String key) {
if (null == paramMap) {
paramMap = new HashMap<String, Object>();
}
return paramMap.get(key);
} /*
* (non-Javadoc)
*
* @see com.junge.threadlocal.context.ThreadContext#getAllParam()
*/
@Override
public Map<String, Object> getAllParam() {
if (null == paramMap) {
paramMap = new HashMap<String, Object>();
}
return paramMap;
} }
3.线程上下文助手ThreadContextHolder
/**
*
*/
package com.junge.threadlocal.context; import java.util.Map; /**
* 线程上下文助手
*
* @author Administrator
*
*/
public class ThreadContextHolder { /**
* 上下文保持对象
*/
private static ThreadLocal<ThreadContext> threadContext = new ThreadLocal<ThreadContext>(); public static void setThreadContext(ThreadContext context) {
threadContext.set(context);
} public static ThreadContext getThreadContext() {
if (null == threadContext.get()) {
threadContext.set(new ThreadContextImpl());
}
return threadContext.get();
} public static void setUserName(String userName) {
getThreadContext().setUserName(userName);
} public static String getUserName() {
return getThreadContext().getUserName();
} public static void setParam1(Object param) {
getThreadContext().setParam1(param);
} public static Object getParam1() {
return getThreadContext().getParam1();
} public static void addParam(String key, Object param) {
getThreadContext().addParam(key, param);
} public static Object getParam(String key) {
return getThreadContext().getParam(key);
} public static Map<String, Object> getAllParam() {
return getThreadContext().getAllParam();
} } 4.线程上下文测试代码
package com.junge.threadlocal.context;
public class ThreadContextHolderTest {
/**
* @param args
*/
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
ThreadContextHolder.setUserName("userName1");
ThreadContextHolder.setParam1(new Object());
ThreadContextHolder.addParam("param1", "aaaa");
System.out.println(Thread.currentThread().getName() + ":"
+ ThreadContextHolder.getUserName());
System.out.println(Thread.currentThread().getName() + ":"
+ ThreadContextHolder.getParam1());
System.out.println(Thread.currentThread().getName() + ":"
+ ThreadContextHolder.getParam("param1"));
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
ThreadContextHolder.setUserName("userName2");
ThreadContextHolder.setParam1(new Object());
ThreadContextHolder.addParam("param1", "bbbb");
System.out.println(Thread.currentThread().getName() + ":"
+ ThreadContextHolder.getUserName());
System.out.println(Thread.currentThread().getName() + ":"
+ ThreadContextHolder.getParam1());
System.out.println(Thread.currentThread().getName() + ":"
+ ThreadContextHolder.getParam("param1"));
}
}).start();
}
}
运行结果:
Thread-0:userName1
Thread-0:java.lang.Object@6e1408
Thread-0:aaaa
Thread-1:userName2
Thread-1:java.lang.Object@e53108
Thread-1:bbbb
ThreadLocal实现线程级上下文的更多相关文章
- Flask中的ThreadLocal本地线程,上下文管理
先说一下和flask没有关系的: 我们都知道线程是由进程创建出来的,CPU实际执行的也是线程,那么线程其实是没有自己独有的内存空间的,所有的线程共享进程的资源和空间,共享就会有冲突,对于多线程对同一块 ...
- 当ThreadLocal碰上线程池
ThreadLocal使用 ThreadLocal可以让线程拥有本地变量,在web环境中,为了方便代码解耦,我们通常用它来保存上下文信息,然后用一个util类提供访问入口,从controller层到s ...
- ThreadLocal解决线程安全问题
一.线程安全问题产生的原因 线程安全问题都是由全局变量及静态变量引起的 二.线程安全问题 SimpleDateFormate sdf = new SimpleDateFormat();使用sdf.pa ...
- java笔记--用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程
用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程 ThreadLocal在我的笔记"关于线程同步"的第5种方式里面有介绍,这里就不多说了. ...
- ThreadLocal本地线程变量的理解
一般的Web应用划分为展现层.服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用.在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程. ...
- ThreadLocal与线程池使用的问题
感谢博主的这篇分享,见 https://www.cnblogs.com/qifenghao/p/8977378.html 在今天的面试中,突然被考官问了这个问题,当时脱口而出的是 threadloca ...
- ThreadLocal和线程同步机制对比
共同点: ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题. 区别: 在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量. 这时该变量是多个线程共享的,使用同 ...
- ThreadLocal实现线程范围的共享变量
一.如何理解线程范围内共享数据 1.static int num=0; 2.线程1访问num变量,并设置为num=2:线程2访问num变量,并设置为num=3: 3.当线程1中对象A.B.C 在访问线 ...
- 多线程篇四:ThreadLocal实现线程范围内变量共享
1.static实现线程范围内变量共享 package com.test.shareData; import java.util.Random; /** * 多线程范围内的数据共享 * @author ...
随机推荐
- 使用VNC连接管理VPS
本文基于:Kvm+Windows2008 VPS+VNCviewer 有时候遇上IP没设置好,IP被封,调整磁盘,重置windows系统密码等等使用基于VNC的控制台对VPS进行操作是非常方便的. 有 ...
- Trapping Rain Water LT42
The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of ...
- IOS初级:story board的跳转
本文要实现view1跳到view2,view2又跳回view1. 首先要在视图中拉出一条连接view1和view2的线. 下面是在view1的控制器中实现,从view1跳到view2 //发生跳转前会 ...
- Java学习笔记:多线程(一)
Java中线程的五种状态: 新建状态(New) 就绪状态(Runnable) 运行状态(Running) 阻塞状态(Blocked) 凋亡状态(Dead) 其中阻塞状态(Blocked)又分为三种: ...
- Spring Boot学习笔记:kafka应用
Kafka作为众多Java消息中间件之一,有诸多优点.本文讲解Kafka的应用.学习一个新的知识点,建议先找一个demo,越简单越好的demo,跑通这个demo,了解大致原理,然后在分析细节,详细了解 ...
- [C#.Net]启动外部程序的几种常用方法汇总
本文汇总了C#启动外部程序的几种常用方法,非常具有实用价值,主要包括如下几种方法: 1. 启动外部程序,不等待其退出. 2. 启动外部程序,等待其退出. 3. 启动外部程序,无限等待其退出. 4. 启 ...
- NOIP水题测试(2017082401)
哈,水题测试又来了! 上次的水题简单吧! 答案是以单题形式发布的(旅行家的预算随后发布). 下面来看今天的题,还是水题. 时间限制:5小时 题目一:看上去就很水 题目二:比上面一题还水 题目三:数的划 ...
- 透过摩拜和ofo,看产品从0到1时如何取舍需求(转)
大纲 背景介绍 从0至1,我们成功的关键是什么? 从0到1,我们为什么选择做?又为什么选择不做? 从0到1,我们面临什么选择?我们作出了什么选择? 从0到1,我们为什么作出了这种选择? 背景 在资本注 ...
- php多表查询数据合并,避免foreach循环嵌套
$memberList = $member->getMemberList(); $members = []; if (is_array($memberList)) { foreach ($mem ...
- mysql学习之路_乱码问题
中文数据问题: 中文数据问题本质就说字符集问题, 计算机只识别二进制,人类识别符号:需要友谊个二进制与字符对应关系(字符集). 报错:服务器没有识别对应的四个字节. 服务器认为的数据是utf—8,一个 ...