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 ...
随机推荐
- Eclipse设置jre版本 或者 jdk
设置Eclipse默认的 JRE 版本 Eclipse 配置 JDK 的方法和配置 JRE 相同 windows --> Preferences --> Java --> 完成后查看 ...
- start()方法和run()方法有什么区别?
通过调用线程类的start()方法来启动一个线程,使线程处于就绪状态,即可以被JVM来调度执行,在调度过程中,JVM通过调用线程类的run()方法来完成实际的业务逻辑,当run()方法结束后,此线程就 ...
- android udp 无法收到数据 (模拟器中)
解决方法:1. 运行模拟器2. 打开window 命令行执行:telnet localhost 55545554是模拟器的端口,执行之后会进入android console3. 在console下执行 ...
- JDK8集合类源码解析 - HashSet
HashSet 特点:不允许放入重复元素 查看源码,发现HashSet是基于HashMap来实现的,对HashMap做了一次“封装”. private transient HashMap<E,O ...
- requestAnimationFrame 完美兼容封装
完美兼容封装: (function() { var lastTime = 0; var vendors = ['webkit', 'moz']; for(var x = 0; x < vendo ...
- fastcgi vc6.0demo
#include <WinSock2.h> #include <stdio.h> #pragma comment(lib, "ws2_32.lib") ty ...
- Spring Boot学习笔记:传统maven项目与采用spring boot项目区别
项目结构区别 传统的maven构建的项目结构如下: 用maven构建的采用springboot项目结构如下: 二者结构一致,区别如下:传统项目如果需要打成war包,需要在WEB-INF目录结构配置we ...
- [C#.Net]启动外部程序的几种常用方法汇总
本文汇总了C#启动外部程序的几种常用方法,非常具有实用价值,主要包括如下几种方法: 1. 启动外部程序,不等待其退出. 2. 启动外部程序,等待其退出. 3. 启动外部程序,无限等待其退出. 4. 启 ...
- 使用adb shell 模拟点击事件
针对问题[appium无法点击到某一内容,需要使用adb去执行点击事件] 需要命令: adb shell adb devices input [input可以实现的功能]: 输入文本信息:input ...
- nginx反向代理缓存服务器的构建
一:代理服务可简单的分为正向代理和反向代理: 正向代理:用于代理内部网络对Internet的连接请求(如VPN/NAT),客户端指定代理服务器,并将本来要直接发送给目标Web服务器的HTTP请求先发送 ...