Java Thread Local – How to use and code sample(转)
转载自:https://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/
Thread Local is an interesting and useful concept, yet most of the Java developers are not aware of how to use that. In this post, I’ll explain what is Thread Local and when to use it, with an example code.
Since it’ll be little tough to understand this concept at first, I’ll keep the explanation as simple as possible (corollary: you shouldn’t use this code as it is in a production environment. Grasp the concept and modify upon it!)
Let’s begin.
What is Thread Local?
Thread Local can be considered as a scope of access, like a request scope or session scope. It’s a thread scope. You can set any object in Thread Local and this object will be global and local to the specific thread which is accessing this object. Global and local!!? Let me explain:
- Values stored in Thread Local are global to the thread, meaning that they can be accessed from anywhere inside that thread. If a thread calls methods from several classes, then all the methods can see the Thread Local variable set by other methods (because they are executing in the same thread). The value need not be passed explicitly. It’s like how you use global variables.
- Values stored in Thread Local are local to the thread, meaning that each thread will have its own Thread Local variable. One thread can not access/modify other thread’s Thread Local variables.
Well, that’s the concept of Thread Local. I hope you understood it (if not, please leave a comment).
When to use Thread Local?
We saw what is thread local in the above section. Now let’s talk about the use cases. i.e. when you’ll be needing something like Thread Local.
I can point out one use case where I used thread local. Consider you have a Servlet which calls some business methods. You have a requirement to generate a unique transaction id for each and every request this servlet process and you need to pass this transaction id to the business methods, for logging purpose. One solution would be passing this transaction id as a parameter to all the business methods. But this is not a good solution as the code is redundant and unnecessary.
To solve that, you can use Thread Local. You can generate a transaction id (either in servlet or better in a filter) and set it in the Thread Local. After this, what ever the business method, that this servlet calls, can access the transaction id from the thread local.
This servlet might be servicing more that one request at a time. Since each request is processed in separate thread, the transaction id will be unique to each thread (local) and will be accessible from all over the thread’s execution (global).
Got it!?
How to use Thread Local?
Java provides a ThreadLocal object using which you can set/get thread scoped variables. Below is a code example demonstrating what I’d explained above.
Lets first have the Context.java
file which will hold the transactionId field.
- package com.veerasundar;
- public class Context {
- private String transactionId = null;
- /* getters and setters here */
- }
Now create the MyThreadLocal.java
file which will act as a container to hold our context object.
- package com.veerasundar;
- /**
- * this class acts as a container to our thread local variables.
- * @author vsundar
- *
- */
- public class MyThreadLocal {
- public static final ThreadLocal userThreadLocal = new ThreadLocal();
- public static void set(Context user) {
- userThreadLocal.set(user);
- }
- public static void unset() {
- userThreadLocal.remove();
- }
- public static Context get() {
- return userThreadLocal.get();
- }
- }
In the above code, you are creating a ThreadLocal object as a static field which can be used by rest of the code to set/get thread local variables.
Let’s create our main class file which will generate and set the transaction ID in thread local and then call the business method.
- package com.veerasundar;
- public class ThreadLocalDemo extends Thread {
- public static void main(String args[]) {
- Thread threadOne = new ThreadLocalDemo();
- threadOne.start();
- Thread threadTwo = new ThreadLocalDemo();
- threadTwo.start();
- }
- @Override
- public void run() {
- // sample code to simulate transaction id
- Context context = new Context();
- context.setTransactionId(getName());
- // set the context object in thread local to access it somewhere else
- MyThreadLocal.set(context);
- /* note that we are not explicitly passing the transaction id */
- new BusinessService().businessMethod();
- MyThreadLocal.unset();
- }
- }
Finally, here’s the code for the BusinessService.java
which will read from thread local and use the value.
- package com.veerasundar;
- public class BusinessService {
- public void businessMethod() {
- // get the context from thread local
- Context context = MyThreadLocal.get();
- System.out.println(context.getTransactionId());
- }
- }
- Thread-
- Thread-
As you might see, even though we are not explicitly passing the transaction id, the value can be accessed from the business method and printed on the console. Adding to it, the transaction ID differs for each thread (0 and 1).
Well, that’s it. I hope I’d explained it in a simple possible way. Please let me know what do you think about this article in comments. Do leave a comment if you want to add anything to this topic.
问:Very nice article. Thanks for sharing.
One question, userThreadLocal of MyThreadLocal class is declared as public static final.
That mean, only one userThreadLocal is created.
So why Thread-0 is not over-written by Thread-1?
答:
Think of "ThreadLocal<t>" as "Map<thread, t="">" conceptually.
If a thread invokes userThreadLocal.get(), it's equivalent to think as map.get(Thread.currentThread().getId())
Now whenever a thread invokes userThreadLocal for the first time, the `initialValue()` of the `ThreadLocal` class gets called. A thread can set the value of (as if it were a thread's own copy) userThreadLocal by userThreadLocal.set() method. And now when the thread calls userThreadLocal.get(), the newly set value is returned.
问: I might have confused the concepts: Taking the example of a unique transaction id for business...Why just not generate the uuid using a random number a generator and pass this uuid to the business method in a regular variable?
答:Because you might not be accessing the id in a function being called directly. You might need to go through several layers of function calls before getting to the business logic - this makes it tedious to change all those functions. Using the ThreadLocal storage makes is convenient, but it should be used with caution.
Java Thread Local – How to use and code sample(转)的更多相关文章
- Java进阶(七)正确理解Thread Local的原理与适用场景
原创文章,始自发作者个人博客,转载请务必将下面这段话置于文章开头处(保留超链接). 本文转发自技术世界,原文链接 http://www.jasongj.com/java/threadlocal/ Th ...
- Java thread jargon
In Java thread topic, the task to be executed and the thread to drive the task are two concepts shou ...
- 性能分析之-- JAVA Thread Dump 分析综述
性能分析之-- JAVA Thread Dump 分析综述 一.Thread Dump介绍 1.1什么是Thread Dump? Thread Dump是非常有用的诊断Java应用问题的工 ...
- java基础知识回顾之java Thread类学习(十)--线程的状态以及转化使用的方法介绍
线程的概述: 线程是程序的多个执行路径,执行调度的单位,依托于进程存在.线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间叫做线程栈,是建立线程的时候由系 ...
- java Thread 类的源码阅读(oracle jdk1.8)
java线程类的源码分析阅读技巧: 首先阅读thread类重点关注一下几个问题: 1.start() ,启动一个线程是如何实现的? 2.java线程状态机的变化过程以及如何实现的? 3. 1.star ...
- 性能分析之– JAVA Thread Dump 分析
最近在做性能测试,需要对线程堆栈进行分析,在网上收集了一些资料,学习完后,将相关知识整理在一起,输出文章如下. 一.Thread Dump介绍 1.1什么是Thread Dump? Thread Du ...
- 线程TLAB局部缓存区域(Thread Local Allocation Buffer)
TLAB(Thread Local Allocation Buffer) 1,堆是JVM中所有线程共享的,因此在其上进行对象内存的分配均需要进行加锁,这也导致了new对象的开销是比较大的 2,Sun ...
- (转)性能分析之-- JAVA Thread Dump 分析综述
原文链接:http://blog.csdn.net/rachel_luo/article/details/8920596 最近在做性能测试,需要对线程堆栈进行分析,在网上收集了一些资料,学习完后,将相 ...
- Java Thread 的 sleep() 和 wait() 的区别
Java Thread 的使用 Java Thread 的 run() 与 start() 的区别 Java Thread 的 sleep() 和 wait() 的区别 1. sleep ...
随机推荐
- Nutch2.1+solr3.6.1+mysql5.6问题
1.Nutch2.1问题 1.1 问题:导入完成后,Nutch2.1里面runtime仍旧不能运行,出现jobfailed等错误. 解决:runtime里的nutch调试过程和导入Eclipse差不多 ...
- ajax跨域-CORS
CORS:跨域资源共享,是一种跨域访问的W3C标准,它允许浏览器可以跨源服务器进行请求,可以让ajax实现跨域访问.出现跨域问题的原因是浏览器同源策略导致的,协议+域名+端口三者一致被认为是同源.网站 ...
- Tensorflow 细节P-40
1.绝大部分时候都会忽略graph的使用,如下代码所示,学会怎样tf.get_default_graph()是重要的,此外注意变量定义时的初始化必须加 initializer 2.此外,要知道 wri ...
- 动手动脑-------找出指定文件夹下所有扩展名为.txt和.java的文件
思路:首先向获取文件,如果是文件的话,则判断它是否以".txt"或".java"结尾,如果是则输出它的路径.如果是文件夹的话,则需获取子文件,利用递归方法遍历子 ...
- loj #6342. 跳一跳 期望dp
令 $f[i]$ 表示已经到达 $i$ 点,为了到大 $n$ 点还期望需要的时间,随便转移一下就行. 由于本题卡空间,要记得开滚动数组. #include <bits/stdc++.h> ...
- 汇编知识之EIP寄存器
eip寄存器存储着我们cpu要读取指令的地址,没有了它,cpu就无法读取下面的指令(通俗点讲cpu就无法执行.每次相应汇编指令执行完相应的eip值就会增加. 因为80386 cpu的寻址范围是4GB. ...
- UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )
题目: 传送门 题意: 给你一个 n * m 的文本串 T, 再给你一个 r * c 的模式串 S: 问模式串 S 在文本串 T 中出现了多少次. 解: 法一: AC自动机 (正解) 670ms 把模 ...
- RookeyFrame 迁移 线下Model 新增属性 迁移 到数据库
在类库 Rookey.BusSys.Operate(类库) -> InitOperate.cs(类) -> App_Start(方法) 添加代码(举例): ToolOperate.Rep ...
- Java Web之Servlet及Cookie/Session
Servlet参考文献: 1.http://www.cnblogs.com/luoxn28/p/5460073.html 2.http://www.cnblogs.com/xdp-gacl/p/376 ...
- shell脚本编程之条件判断
条件测试类型: 整数测试 字符测试 文件测试 条件测试的表达式的三种方法: 1.[ expression ] 命令测试 2.[[ expression ]] 关键字测试 3.test expressi ...