java ThreadLocal与其应用(netty)
来源:互联网 发布:淘宝售假违规扣24分 编辑:程序博客网 时间:2024/05/22 10:37
刚开始看netty源代码的时候就遇到了ThreadLocal这个东西,当时就不太明白这个东西到底干嘛用的,上网稍微查了一下,好像大家说法都不太一样,有的说是为了方便线程维护自己的变量,有的又说是什么方便并发编程。。我擦。。感觉凌乱了。。还是自己好好看看靠谱。。。
首先ThreadLocal确实是用于线程存储本地变量的一种很不错的方法,在这里,一般情况下,都用于保存当前变量独有的对象实例,如果好多线程都只是保存同一个对象的引用的话,那么就必须加上额外的同步机制了。。所以说这里和并发一毛线关系都没有。。。。
我们还是来看它在netty中是怎么用的吧,在SingleThreadEventExecutor中定义如下:
static final ThreadLocal<SingleThreadEventExecutor> CURRENT_EVENT_LOOP = new ThreadLocal<SingleThreadEventExecutor>(); //线程局部变量这里需要注意的是static。。。。
再来看看如何得到存储的变量呢?
public static SingleThreadEventExecutor currentEventLoop() { return CURRENT_EVENT_LOOP.get(); //返回当前 }这里也是static的。。。
好,接下来我们来看netty是怎么存储线程的本地变量的:
protected SingleThreadEventExecutor( EventExecutorGroup parent, ThreadFactory threadFactory, boolean addTaskWakesUp) { if (threadFactory == null) { throw new NullPointerException("threadFactory"); } this.parent = parent; this.addTaskWakesUp = addTaskWakesUp; //唤醒任务 thread = threadFactory.newThread(new Runnable() { //创建线程 @Override //线程的执行函数 public void run() { CURRENT_EVENT_LOOP.set(SingleThreadEventExecutor.this); //存储当前线程的本地对象 boolean success = false; updateLastExecutionTime(); try { SingleThreadEventExecutor.this.run(); //开始当前executor的执行函数,run方法延后到了后面的类中实现 success = true; } catch (Throwable t) { logger.warn("Unexpected exception from an event executor: ", t); } finally { if (state < ST_SHUTTING_DOWN) { state = ST_SHUTTING_DOWN; } // Check if confirmShutdown() was called at the end of the loop. if (success && gracefulShutdownStartTime == 0) { logger.error( "Buggy " + EventExecutor.class.getSimpleName() + " implementation; " + SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must be called " + "before run() implementation terminates."); } try { // Run all remaining tasks and shutdown hooks. for (;;) { if (confirmShutdown()) { break; } } } finally { try { cleanup(); } finally { synchronized (stateLock) { state = ST_TERMINATED; } threadLock.release(); if (!taskQueue.isEmpty()) { logger.warn( "An event executor terminated with " + "non-empty task queue (" + taskQueue.size() + ')'); } } } } } }); taskQueue = newTaskQueue(); //构造任务队列 }
这里需要注意的是,是在线程的run方法里面调用set方法来保存本地变量的。。
要搞清楚究竟是怎么回事,感觉还是看源码最靠谱。。。。
首先我们来看ThreadLocal构造函数吧:
/** * Creates a thread local variable. */ public ThreadLocal() { }空方法,白看了。。。
好吧接下来来看看set方法吧:
public void set(T value) { Thread t = Thread.currentThread(); //当前的运行线程 ThreadLocalMap map = getMap(t); //额,就当是获取一个map吧 if (map != null) map.set(this, value); //标准的map的set方法,key就是当前的ThreadLocal变量 else createMap(t, value); //创建map,并保存 }这里居然出现了一个map,而且这里保存value的时候用的key就是当前的ThreadLocal变量。。。
还是来看看getMap方法,看看map究竟从哪里搞出来的吧。。。
ThreadLocalMap getMap(Thread t) { return t.threadLocals; }这里传进的t就是当前正在执行的线程,可以看出这个map其实就是当前的执行线程的一个属性。。。
嗯,其实看到这里,基本上就明白的差不多了。。。。不过还是来看看get方法吧:
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); //跟上面的套路差不多吧,获取map if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); //用当前的ThreadLocal为key,获取value if (e != null) return (T)e.value; } return setInitialValue(); }
嗯,这个还是比较简单的吧。。。一看就差不多明白什么意思了。。。
好了,ThreadLocal基本的一些概念算是搞清楚了。。。
(1)每一个Thread变量本身就保存有一个map对象(姑且把它理解为map吧)
(2)当set的时候,实际上是将当前的value放入到当前执行线程的那个map当中去,而且这里的key就是当前的ThreadLocal对象。。。
好了,其实这里也能想到ThreadLocal的用法了,在netty中的代码,访问的方法都是static(上面我故意表黑,变大),说明这是为了方便线程能够访问这些变量,而不用将这些变量在对象中传来传去的。。方便的多了。。。可以少写很多的代码。。。
- java ThreadLocal与其应用(netty)
- Java中ThreadLocal应用总结(1)
- Java中ThreadLocal应用总结(2)
- ThreadLocal在Java中的应用
- 阅读-ThreadLocal(JAVA)
- java中ThreadLocal的一个应用
- 【java并发】ThreadLocal类以及应用技巧
- Java解读-ThreadLocal详解与应用
- ThreadLocal应用
- ThreadLocal应用
- netty应用
- java多线程(一) ThreadLocal
- ThreadLocal原理与应用详解(1)
- ThreadLocal原理与应用详解(2)
- errno与其应用
- java-Netty学习(2)
- netty(七)netty入门应用
- java ThreadLocal
- comm物件对比
- java.util.concurrent介绍
- POJ 2486
- clr 工程设置 调试
- 学习笔记(updating ...)
- java ThreadLocal与其应用(netty)
- 2013.7.18 acm_schooltraining解题报告
- Oracle发布最新数据库补丁(2013-7)
- Linux下安装TFTP
- Linux CGI编程
- kaixin
- Importing and Exporting in Studio
- python编写shell脚本详细讲解
- 递归举例