ThreadLocal的使用方法
来源:互联网 发布:软件测试工作感想 编辑:程序博客网 时间:2024/06/14 22:11
运行的时候,每个Player Thread都是去调用Attemp.guess()方法,进而操作同一个ThreadLocal变量history,但却可以保存每个线程自己的数据,这就是ThreadLocal的作用。
<span style="font-family:Courier New;">public class ThreadLocalTest { public static void main(String[] args) { Judge.prepare(); new Player(1).start(); new Player(2).start(); new Player(3).start(); } }class Judge { public static int MAX_VALUE = 10; private static int targetValue; public static void prepare() { Random random = new Random(); targetValue = random.nextInt(MAX_VALUE) + 1; } public static boolean judge(int value) { return value == targetValue; } }class Player extends Thread { private int playerId; public Player(int playerId) { this.playerId = playerId; } @Override public void run() { boolean success = false; while(!success) { int value = Attempt.guess(Judge.MAX_VALUE); success = Judge.judge(value); System.out.println(String.format("Plyaer %s Attempts %s and %s", playerId, value, success ? " Success" : "Failed")); } Attempt.review(String.format("[IFNO] Plyaer %s Completed by ", playerId)); } }class Attempt { private static ThreadLocal<Record> history = new ThreadLocal<Record>(); public static int guess(int maxValue) { Record record = getRecord(); Random random = new Random(); int value = 0; do { value = random.nextInt(maxValue) + 1; } while (record.contains(value)); record.save(value); return value; } public static void review(String info) { System.out.println(info + getRecord()); } private static Record getRecord() { Record record = history.get(); if(record == null) { record = new Record(); history.set(record); } return record; } }class Record { private List<Integer> attemptList = new ArrayList<Integer>();; public void save(int value) { attemptList.add(value); } public boolean contains(int value) { return attemptList.contains(value); } @Override public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(attemptList.size() + " Times: "); int count = 1; for(Integer attempt : attemptList) { buffer.append(attempt); if(count < attemptList.size()) { buffer.append(", "); count++; } } return buffer.toString(); } }</span>
运行结果:
Plyaer 1 Attempts 8 and Failed
Plyaer 1 Attempts 3 and Failed
Plyaer 1 Attempts 2 and Success
[IFNO] Plyaer 1 Completed by 3 Times: 8, 3, 2
Plyaer 3 Attempts 5 and Failed
Plyaer 3 Attempts 8 and Failed
Plyaer 3 Attempts 7 and Failed
Plyaer 3 Attempts 1 and Failed
Plyaer 3 Attempts 3 and Failed
Plyaer 3 Attempts 10 and Failed
Plyaer 3 Attempts 2 and Success
[IFNO] Plyaer 3 Completed by 7 Times: 5, 8, 7, 1, 3, 10, 2
Plyaer 2 Attempts 10 and Failed
Plyaer 2 Attempts 9 and Failed
Plyaer 2 Attempts 4 and Failed
Plyaer 2 Attempts 6 and Failed
Plyaer 2 Attempts 5 and Failed
Plyaer 2 Attempts 3 and Failed
Plyaer 2 Attempts 7 and Failed
Plyaer 2 Attempts 1 and Failed
Plyaer 2 Attempts 2 and Success
[IFNO] Plyaer 2 Completed by 9 Times: 10, 9, 4, 6, 5, 3, 7, 1, 2
关于ThreadLocal的原理,可以从其get()方法的实现来看
<span style="font-family:Courier New;">public class ThreadLocal<T> { ... public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue(); } ThreadLocalMap getMap(Thread t) { return t.threadLocals; } ...}</span>
执行get()时首先获取当前的Thread,再获取Thread中的ThreadLocalMap - t.threadLocals,并以自身为key取出实际的value。于是可以看出,ThreadLocal的变量实际还是保存在Thread中的,容器是一个Map,Thread用到多少ThreadLocal变量,就会有多少以其为key的Entry。
总结
1、ThreadLocal是使用的一种线程的局部变量。
2、使用ThreadLocal可以很好每次都使用开始创建的那个对象。
3、Hibernate中就使用ThreadLocal来获取当前事务的处理。
4、ThreadLocal使用场合主要解决多线程中数据数据因并发产生不一致问题。比如实际项目中我不想使用MVC框架,而使用自己简易线程安全的MVC框架,可以将request和response对象存放在ThreadLocal对象中,这样访问的就是已存在的request和response变量:
/** * 将request,response放到ThreadLocal方便普通java类调用 */public class MyCustomContext {private static ThreadLocal<HttpServletRequest> myRequest = new ThreadLocal<HttpServletRequest>();private static ThreadLocal<HttpServletResponse> myResponse = new ThreadLocal<HttpServletResponse>();/** * 获取当前登录用户 */public static SysUserEntity getLoginUser() {return (SysUserEntity) getMySession().getAttribute("login_user");}/** * 将request、response放入ThreadLocal容器 */public static void setAll(HttpServletRequest request,HttpServletResponse response){myRequest.set(request);myResponse.set(response);}/** * 获得request * @return */public static HttpServletRequest getMyRequest(){return myRequest.get();}/** * 获得session */public static HttpSession getMySession(){HttpServletRequest request = getMyRequest();if(null == request){throw new MyRuntimeException("myRequest未赋值,无法获取session");}return request.getSession();}public static void setMyRequest(HttpServletRequest request){myRequest.set(request);}/** * 获得response */public static HttpServletResponse getMyResponse(){return myResponse.get();}public static void setMyRequest(HttpServletResponse response){myResponse.set(response);}public static void removeMyRequest(){myRequest.remove();}public static void removeMyResponse(){myResponse.remove();}public static void remoceAll(){myRequest.remove();myResponse.remove();}}
- ThreadLocal的使用方法
- ThreadLocal的使用方法
- ThreadLocal的使用方法
- ThreadLocal的使用方法
- ThreadLocal的理解和使用方法
- java ThreadLocal使用方法
- ThreadLocal内部机制及使用方法
- ThreadLocal的应用(z)
- ThreadLocal 的技术文章
- ThreadLocal的相关资料
- ThreadLocal的使用- -
- ThreadLocal的使用
- 对ThreadLocal的理解
- ThreadLocal 的使用
- ThreadLocal的使用
- 关于ThreadLocal的使用
- Threadlocal类的使用
- ThreadLocal的理解
- ACM感悟
- Linux下修改文件的时间属性
- 第9周项目6-穷举法解决组合问题之换分币
- Useful Articles for the Oracle E-Business Suite Technology Stack for Technical Consultant / DBA [ID
- java 10.23(时钟)
- ThreadLocal的使用方法
- struts2表单提交乱码问题解决办法
- Linux下FrameBuffer直接写屏
- Android 完全自定义对话框的实现(标题栏+EditText+双按钮)
- .ifnz UART_SUPPORT
- 将UE4代码编译成32位的编辑器
- 给14级软件5班同学的答疑(20141017)
- mysql 数据库 锁状态查看
- 《人工智能(智能系统指南,第二版)》读书笔记——5、第四章