ThreadLocal提供了线程本地变量,它可以保证访问到的变量属于当前线程,每个线程都保存有一个变量副本,每个线程的变量都不同。ThreadLocal相当于提供了一种线程隔离,将变量与线程相绑定。
Threadloca适用于在多线程的情况下,可以实现传递数据,实现线程隔离。
1.New Threadlocal();---创建Threadlocal
2.set 设置当前线程绑定的局部变量
3.get 获取当前线程绑定的局部变量
4.remove() 移除当前线程绑定的变量
根据子线程 在Threadlocal存放局部变量,但是获取的时候是主线程,所以
无法获取。
Synchronized与Threadlocal 都可以实现多线程访问,保证线程安全的问题。
Synchronized采用当多个线程竞争到同一个资源的时候,最终只能够有一个线程访问,采用时间换空间的方式,保证线程安全问题
B.Threadlocal在每个线程中都自己独立的局部变量, 空间换时间,相互之间都是隔离。
相比来说Threadlocal效率比Synchronized效率更高。
public class Test004 { private String context; public String getContext() { return threadLocal.get(); // return context; } public void setContext(String context) { // this.context = context; threadLocal.set(context); } private static Object lock = new Object(); private static ThreadLocal<String> threadLocal = new ThreadLocal<>(); public static void main(String[] args) { Test004 test004 = new Test004(); for (int i = 0; i < 5; i++) { int finalI = i; new Thread(() -> { // synchronized (lock) { test004.setContext(Thread.currentThread().getName() + "," + finalI); try { Thread.sleep(500); } catch (Exception e) { } System.out.println("线程id:" + Thread.currentThread().getName() + "," + test004.getContext()); // } }, i + "").start(); } } }
指程序在申请内存时,没有足够的内存空间供其使用,出现 out of memory。 OOM溢出
程序在申请内存时,没有足够的内存空间使用,一般解决办法:加内存。
指程序在申请内存后,无法释放已申请的内存空间,内存泄露堆积会导致内存被占光,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
强引用:被引用关联的对象永远不会被垃圾收集器回收
软引用:软引用关联的对象,只有当系统内存溢出时,才会回收软引用的对象。
弱引用:只被弱引用关联的对象,当垃圾回收机制触发的时候就会被回收。
强引用:强引用关联的对象永远是无法被我们垃圾收集器回收。
弱引用:弱引用关联的对象,当垃圾回收机制触发的时候就会被回收。
Object obj = new Object(),这里的的obj就是强引用,通过关键字new创建的对象所关联的引用就是强引用。 只要有强引用指向一个对象,就能表明对象还活着,垃圾收集器就不会触碰这种对象,当JVM内存空间不足,JVM宁愿抛出OutOfMemoryError运行时错误(OOM),使程序异常终止,也不会靠随意回收具有强引用的“存活”对象来解决内存不足的问题。对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用赋值为 null,就是可以被垃圾收集的了,具体回收时机还是要看垃圾收集策略
public class Test005 { public static void main(String[] args) { OrderEntity order1 = new OrderEntity("agsdgs", "hasdx"); // 强引用 // OrderEntity order2 = order1; // order1 = null; // System.out.println(order2); // System.gc(); // System.out.println(order2); // 弱引用 WeakReference<OrderEntity> order2 = new WeakReference<>(order1); order1 = null; System.out.println(order2.get()); System.gc(); System.out.println(order2.get()); } }
在每个线程中都有自己独立的ThreadLocalMap对象,中Entry对象。如果当前线程对应的的ThreadLocalMap对象为空的情况下,则创建该ThreadLocalMap
对象,并且赋值键值对。
Key 为 当前new ThreadLocal对象,value 就是为object变量值。
因为每个线程中都有自己独立的ThreadLocalMap对象,key为ThreadLocal,value 是为
变量值。
Key为ThreadLocal 作为Entry对象的key,是弱引用,当ThreadLocal指向null的时候,
Entry对象中的key变为null,该对象一直无法被垃圾收集机制回收,一直占用到了系统内存,有可能会发生内存泄漏的问题。
public class Test006 { private static ThreadLocal threadLocal = new ThreadLocal<String>(); public static void main(String[] args) { threadLocal.set("dfr"); threadLocal.remove(); threadLocal = null; System.gc(); Thread thread = Thread.currentThread(); threadLocal.get(); } }
1. 可以自己调用remove方法将不要的数据移除避免内存泄漏的问题,
2. 每次在做set方法的时候会清楚之前 key为null
如果key是为强引用: 当我们现在将ThreadLocal 的引用指向为null,但是
每个线程中有自己独立ThreadLocalMap还一直在继续持有该对象,但是我们
ThreadLocal 对象不会被回收,就会发生ThreadLocal内存泄漏的问题。
如果key是为弱引用:
当我们现在将ThreadLocal 的引用指向为null,Entry 中的key指向为null,但是
下次调用set方法的时候,会根据判断如果key空的情况下,直接删除,有可能会发生
Entry 发生内存泄漏的问题。
不管是用强引用还是弱引用都是会发生内存泄漏的问题。
弱引用中不会发生ThreadLocal内存泄漏的问题。
但是最终根本的原因Threadlocal内存泄漏的问题,产生于ThreadLocalMap与
我们当前线程的生命周期一样,如果没有手动的删除的情况下,就有可能会发生内存泄漏的问题。