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 ...
随机推荐
- Nowcoder OI赛制测试2 F 假的数学题 - 斯特林公式 + 二分
Description 给定$X$, 找到最小的$N$ 使得$N! > X^X$ 数据范围: $x <= 1e11$ Solution $X^X$ 太大, 高精也存不过, 所以取对数 : ...
- Codeforces 803C. Maximal GCD 二分
C. Maximal GCD time limit per test: 1 second memory limit per test: 256 megabytes input: standard in ...
- UVA 11324.The Largest Clique tarjan缩点+拓扑dp
题目链接:https://vjudge.net/problem/UVA-11324 题意:求一个有向图中结点数最大的结点集,使得该结点集中任意两个结点u和v满足:要目u可以到达v,要么v可以到达u(相 ...
- Zookeeper 修改heap size
对应原文出处: https://support.pivotal.io/hc/en-us/articles/201861286-Zookeeper-service-heapsize-is-10GB-or ...
- ubuntu增加工作分区命令
参考自: https://www.cnblogs.com/wolflowhereu/p/5422653.html ubuntu增加工作分区(workspace)命令 dconf write /org ...
- How to ignore files and directories in subversion?
Step 1 Copy the files and directories to other place. Step 2 Delete the files and directories. Step ...
- Web应用获取文件路径的方法
拥有 HttpServletRequest req 对象 req.getSession().getServletContext().getRealPath("/") ----- ...
- css固宽截取字符串
width:200px; white-space:nowrap; word-break:keep-all; overflow:hidden; text-overflow:ellipsis; 移动端支持 ...
- oracle 替换字符 replace
替换字符: select replace('xxyyzz','zz','') from dual >> xxyy 同时替换多个字符: select replace(replace('x ...
- php使用include报错require_once(../include.php): failed to open stream: No such file or directo
引入路径的问题,建议加入include_once $_SERVER['DOCUMENT_ROOT']."/include.php";意思是获取网站根目中的include.php 截 ...