b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

FOEVERYANG

电脑杂谈  发布时间:2020-05-23 19:05:10  来源:网络整理

xpath实例使用详解_threadlocal使用实例_threadlocal使用实例

ThreadLocal是JDK软件包提供的线程局部变量. 如果创建了ThreadLocal 变量,则访问该变量的每个线程都将拥有该变量的副本. 在实际的多线程操作中,您自己在本地内存中操作变量,以避免线程安全问题.

ThreadLocal很容易让人看到,并假定为“本地线程”. 实际上,ThreadLocal不是线程,而是Thread的局部变量. 通过将其命名为ThreadLocalVariable也许更容易理解它.

请看官方定义: 此类提供线程局部变量. 这些变量与普通变量不同. 每个访问一个线程(通过其get或set方法)的线程都有自己的变量副本,该副本独立初始化. ThreadLocal实例通常是该类中的一个私有静态字段,并且您想将状态与线程关联(例如,用户ID或事务ID).

 1     /**
 2      * Sets the current thread's copy of this thread-local variable
 3      * to the specified value.  Most subclasses will have no need to
 4      * override this method, relying solely on the {@link #initialValue}
 5      * method to set the values of thread-locals.
 6      *
 7      * @param value the value to be stored in the current thread's copy of
 8      *        this thread-local.
 9      */
10     public void set(T value) {
11         Thread t = Thread.currentThread();
12         ThreadLocalMap map = getMap(t);
13         if (map != null)
14             map.set(this, value);
15         else
16             createMap(t, value);
17     }

分析:

在调用ThreadLocal的集合(T t)时,代码将首先获取当前线程的ThreadLocalMap(ThreadLocal中的静态内部类,并且还作为Thread的成员变量存在,稍后将进一步理解)存在ThreadLocalMap,使用ThreadLocal作为地图的键,然后将要保存的值作为值放入地图中(如果地图不存在,请先创建地图,然后将其放置);

/**
     * Returns the value in the current thread's copy of this
     * thread-local variable.  If the variable has no value for the
     * current thread, it is first initialized to the value returned
     * by an invocation of the {@link #initialValue} method.
     *
     * @return the current thread's value of this thread-local
     */
    public T get() {
       Thread t = Thread.currentThread();
       ThreadLocalMap map = getMap(t);        //此处和set方法一致,也是通过当前线程获取对应的成员变量ThreadLocalMap,map中存放的是Entry(ThreadLocalMap的内部类(继承了弱引用))
    
if (map != null) {
      ThreadLocalMap.Entry e = map.getEntry(this);
      if (e != null) {
        @SuppressWarnings("unchecked")
        T result = (T)e.value;
        return result;
      }
    }
    return setInitialValue();
}

分析:

threadlocal使用实例_xpath实例使用详解_threadlocal使用实例

我只是将对象放入地图集中,现在根据键将其取出. 值得注意的是,这里的映射不存储键值对,而是继承WeakReference >关于ThreadLocalMap.Entry类的对象,稍后将有更详细的描述.

    /**
     * Removes the current thread's value for this thread-local
     * variable.  If this thread-local variable is subsequently
     * {@linkplain #get read} by the current thread, its value will be
     * reinitialized by invoking its {@link #initialValue} method,
     * unless its value is {@linkplain #set set} by the current thread
     * in the interim.  This may result in multiple invocations of the
     * {@code initialValue} method in the current thread.
     *
     * @since 1.5
     */
     public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }

分析:

通过getMap方法获取Thread中的成员变量ThreadLocalMap,在映射中删除相应的ThreadLocal,因为ThreadLocal(键)是一个弱引用,弱引用中的键为空,gc将恢复变量值,取看一下核心M.remove(this);方法

        /**
         * Remove the entry for key.
         */
        private void remove(ThreadLocal<?> key) {
            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1); //定义Entry在数组中的标号
            for (Entry e = tab[i];              //通过循环的方式remove掉Thread中所有的Entry
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {   
                if (e.get() == key) {
                    e.clear();
                    expungeStaleEntry(i);
                    return;
                }
            }
        } 

问: threadlocal用于什么场合?在什么情况下使用?

threadlocal使用实例_xpath实例使用详解_threadlocal使用实例

结合ThreadLocal类的正式定义,threadLocal主要满足某些变量或示例是线程隔离的,但可以在同一线程的多个类或方法中使用,并且该变量也应程结束时使用破坏. 用外行的话来说: ThreadLocal确保每个线程都有自己的数据副本,这些副本可以程结束后独立回收. 由于ThreadLocal的特性,同一线程设置在某个位置,并且可以在任何后续位置获取. 它可以用来保存线程上下文信息. 例如,常用的方法是如何将一系列后续操作与每个请求相关联,您可以使用ThreadLocal进行设置,在需要记录的任何后续方法中获取请求ID,以便对整个请求进行字符串化.

有许多使用方案,例如:

问: 如果我启动另一个线程. 子线程可以获取在主线程上设置的Threadlocal值吗?

原始ThreadLocal没有继承(或转移)特征

问: 如何解决ThreadLocal无法通过的问题?

InheritableThreadLocal,ThreadLocal的子类,InheritableThreadLocal是可传递的

  /**
  * 重写Threadlocal类中的getMap方法,在原Threadlocal中是返回
  * t.theadLocals,而在这么却是返回了inheritableThreadLocals,因为
  * Thread类中也有一个要保存父子传递的变量
  */ ThreadLocalMap getMap(Thread t) {
return t.inheritableThreadLocals; }

    /**
     * 同理,在创建ThreadLocalMap的时候不是给t.threadlocal赋值
     *而是给inheritableThreadLocals变量赋值
     * 
     */

xpath实例使用详解_threadlocal使用实例_threadlocal使用实例

    void createMap(Thread t, T firstValue) {
        t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
    }

分析: 因为InheritableThreadLocal重写ThreadLocal中的getMap和createMap方法,所以这两个方法在Thread中维护了另一个成员变量InheritableThreadLocals. 创建线程后,将回传InheritableThreadLocals中的值;

/* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
  //Thread类中维护的成员变量,ThreadLocal会维护该变量
ThreadLocal.ThreadLocalMap threadLocals = null; /* * InheritableThreadLocal values pertaining to this thread. This map is * maintained by the InheritableThreadLocal class. */
//Thread中维护的成员变量 ,
InheritableThreadLocal 中维护该变量

ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;


//Thread init方法中的关键代码,简单来说是将父类中inheritableThreadLocals中的值拷贝到当前线程的inheritableThreadLocals中(浅拷贝,拷贝的是value的地址引用)

 if (inheritThreadLocals && parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

提示: 以上四个摘要来自其他技术博客. 我个人认为摘要是更合理的,所以我直接提取了它们

扩展:

threadlocal使用实例_xpath实例使用详解_threadlocal使用实例

ThreadLocal程池中易于使用: 内存泄漏,请首先查看下图

每个线程中都有一个映射. 映射的类型是ThreadLocal.ThreadLocalMap. 映射中的键是threadlocal实例. 该映射确实使用弱引用,但弱引用仅用于键. 每个键都是弱引用指向threadlocal. 当threadlocal实例设置为null时,没有对threadlocal实例的强引用,因此gc将恢复threadlocal. 但是,由于当前线程连接了一个强引用,因此无法恢复我们的值. 只有在当前线程结束之后,当前线程才会在堆栈中不存在,强引用将断开连接,并且当前线程Map值将全部由GC恢复.

因此,可以得出结论,只要gc回收了线程对象,就不会发生内存泄漏threadlocal使用实例,但是当threadLocal设置为null且线程结束时,它将不会被回收,我们认为发生内存泄漏. 实际上,这是对该概念的不一致理解,没有什么可争论的. 最可怕的是线程对象没有被回收,这导致了真正的内存泄漏. 例如,当使用线程池时,线程的末尾不会被破坏,而是会再次使用. 可能有内存泄漏.

PS.Java为了最大程度地减少内存泄漏的可能性和影响,在ThreadLocal get和set期间将清除Thread Map中的所有get null值. 因此,最令人担忧的情况是将threadLocal对象设置为null,然后开始“内存泄漏”,然后使用线程池. 该线程结束,并且线程被放回线程池而不被破坏. 不再调用get,set方法,则在此期间将发生实际内存泄漏.

JVM使用ThreadLocalMap Key作为弱引用以避免内存泄漏. JVM使用remove,get和set方法恢复弱引用. 当ThreadLocal用null键存储许多Entry时,而不是调用remove,get,set方法threadlocal使用实例,这将导致内存泄漏. 使用静态ThreadLocal时,延长ThreadLocal的生命周期,也可能导致内存泄漏. 因为静态变量是在未加载类时加载的,所以当线程结束时,静态变量可能不会被回收. 然后,与仅在使用时加载普通成员变量相比,静态生命周期将更可能导致内存泄漏危机.

参考链接:

通过以上分析,我们可以知道InheritableThreadLocal是通过Thread()的inint方法在父级和子级之间传递的,但是线程池被统一以创建线程并实现重用,从而发生以下问题: p >

ps: 何时程池中创建线程?

解决方案:

以下两个链接具有详细说明,因此我不再重复. 在后续文章中,我将优化本文并添加一些示例以帮助对其进行解释. 欢迎来到收藏集. 对这篇文章有不同的看法.


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-219717-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...