34 thread

作者: 滔滔逐浪 | 来源:发表于2020-08-05 08:42 被阅读0次

    Thread真实应用场景:
    1,spring 模板方法
    2,spring 编程事务注解
    3,aop
    4,根据当前线程获取Request 对象
    Threadlocal 与Synchronized
    1,共同特征: 都可以解决线程安全问题
    2,Threadlocal占内存,synchronized不是很占内存
    synchronized当多个线程在同时共享到同一个全局变量的时候,只有一个线程对该变量做修改操作,效率非常低,以时间换空间。
    Threadlocal 每个线程有独立的缓存局部变量,

    package com.taotao.threads.days08;
    
    /**
     *@author tom
     *Date  2020/8/1 0001 8:36
     *
     */
    public class Test002 {
        // private String context;
    
        public String getContext() {
            return threadLocal.get();
        }
    
        public void setContext(String context) {
            threadLocal.set(context);
    
        }
    
        private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
    
        private static Object lock = new Object();
    
        public static void main(String[] args) {
            Test002 test002 = new Test002();
            for (int i = 0; i < 500; i++) {
                int finalI = i;
                new Thread(() -> {
                    // synchronized (lock){
    
                    threadLocal.set(Thread.currentThread().getName() + "," + finalI);
                    // test002.context=Thread.currentThread().getName()+","+ finalI;
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(threadLocal.get());
                    //}
                }, i + "").start();
            }
        }
    }
    
    

    什么是内存溢出:
    程序在申请内存前的时候。没有足够的内存提供,抛出一个异常oom,加内存
    什么是内存泄露:
    程序申请内存后,内存无法被垃圾回收机制回收,永远无法释放该内存,造成系统内存的浪费。
    1,导致系统卡
    2,有可能申请内存的时候出现内存溢出

    强引用,弱引用:
    强引用: 被引用关联的对象永远不会被垃圾回收机制回收:

    
    package com.taotao.threads.days08;
    
    /**
     *@author tom
     *Date  2020/8/2 0002 9:36
     *强引用
     */
    public class Test003 {
        public static void main(String[] args) {
            OrderEntity o1=new OrderEntity(11,"333");
                OrderEntity o2=o1;
            System.out.println(o2);
            o1=null;
            System.gc();
            System.out.println(o2);
    
        }
    }
    
    
    package com.taotao.threads.days08;
    
    /**
     *@author tom
     *Date  2020/8/2 0002 9:36
     *
     */
    public class OrderEntity {
        private int orderId;
        private  String orderName;
    
        public OrderEntity(int orderId, String orderName) {
            this.orderId = orderId;
            this.orderName = orderName;
        }
    
        public int getOrderId() {
            return orderId;
        }
    
        public OrderEntity setOrderId(int orderId) {
            this.orderId = orderId;
            return this;
        }
    
        public String getOrderName() {
            return orderName;
        }
    
        public OrderEntity setOrderName(String orderName) {
            this.orderName = orderName;
            return this;
        }
    }
    
    

    弱引用: 只要被弱引用关联的对象,都会被垃圾回收触发回收机制:

    package com.taotao.threads.days08;
    
    import java.lang.ref.WeakReference;
    
    /**
     *@author tom
     *Date  2020/8/2 0002 9:45
     *软引用:
     */
    public class Test004 {
        public static void main(String[] args) {
            OrderEntity o1=new OrderEntity(2,"3");
            WeakReference<OrderEntity> o2=new WeakReference<>(o1);
                    o1=null;
            System.out.println(o2.get());
            System.gc();
            System.out.println(o2.get());
    
        }
    }
     
    
    

    Thread底层如何实现?
    误区: 不是使用大Map 集合实现
    ThreadLocalMap:

    1,每个线程里有自己独立的ThreadMap 缓存局部变量

        public void set(T value) {
    //获取当前线程
            Thread t = Thread.currentThread();
    //获取当前线程对应的map
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
        }
    
    
    
    
    image.png

    重点: ThreadLocalMap 设置的key为threadlocal

    ThreadLocalMap 底层基于Entry 实现包装。Entry的key 采用弱引用方式指向threadlocal.

    分析为什么hi发生内存泄露的问题:
    内存泄露的概念: 申请内存后,无法被垃圾回收机制回收,一直占用我们的内存空间,有可能会发生内存泄露问题。
    private Entry[] tables;
    如果采用弱引用的情况下,现在将threadlocal指向的地址改为null;
    当触发gc的时候会从堆内存中移除threadLocal,但是我们的Entry的key指向为null。
    但是垃圾回收机制一直无法回收,一直占用内存,所以会发生内存泄露问题。

    1,

    如何避免内存泄露问题
    当我们修改了ThreadLocal指向为null的时候,应该从Entry中移除。
    1,直接调用remove方法。
    2,使用java反射 机制获取当前线程对应的ThreadLocalMap
    手动移除。
    3,下次调用set方法的时候,检测链表zhongkey 如果存在、key为空的情况下直接移除。

    package com.taotao.threads;
    
    /**
     *@author tom
     *Date  2020/8/3 0003 6:59
     *
     */
    public class Test005 {
        private static ThreadLocal<String> threadLocalMap = new ThreadLocal<String>();
    
        public static void main(String[] args) {
            threadLocalMap.set("99");
            threadLocalMap.remove();;
            threadLocalMap=null;
            System.gc();
            Thread thread=Thread.currentThread();
    
            threadLocalMap.get();
        }
    }
    
    
    

    为什么线程中ThreadLocalMap底层数组Entry实现
    Entry key=new ThreadLocal();

    Threadlocal采用弱引用而不是强引用

    如果key是为强引用: 当我们现在将ThreadLocal 的引用指向为null,但是
    每个线程中有自己独立ThreadLocalMap还一直在继续持有该对象,但是我们
    ThreadLocal 对象不会被回收,就会发生ThreadLocal内存泄漏的问题。

    如果key是为弱引用:
    当我们现在将ThreadLocal 的引用指向为null,Entry 中的key指向为null,但是
    下次调用set方法的时候,会根据判断如果key空的情况下,直接删除,有可能会发生
    Entry 发生内存泄漏的问题。

    不管是用强引用还是弱引用都是会发生内存泄漏的问题。
    弱引用中不会发生ThreadLocal内存泄漏的问题。

    但是最终根本的原因Threadlocal内存泄漏的问题,产生于ThreadLocalMap与
    我们当前线程的生命周期一样,如果没有手动的删除的情况下,就有可能会发生内存泄漏的问题。

    相关文章

      网友评论

          本文标题:34 thread

          本文链接:https://www.haomeiwen.com/subject/jhcprktx.html