Juc17_ThreadLocal概述、解决SimpleDateFormat出现的异常、内存泄漏、弱引用、remove方法(一)

简介: ①. ThreadLocal简介①. ThreadLocal是什么②. api介绍③. 永远的helloword④. 通过上面代码总结

①. ThreadLocal简介


①. ThreadLocal是什么


①. ThreadLocal本地线程变量,线程自带的变量副本(实现了每一个线程副本都有一个专属的本地变量,主要解决的就是让每一个线程绑定自己的值,自己用自己的,不跟别人争抢。通过使用get()和set()方法,获取默认值或将其值更改为当前线程所存的副本的值从而避免了线程安全的问题)


②. synchronized或者lock,有个管理员,好比,现在大家签到,多个同学(线程),但是只有一只笔,只能同一个时间,只有一个线程(同学)签到,加锁(同步机制是以时间换空间,执行时间不一样,类似于排队)


微信图片_20220108142243.png


③. ThreadLocal,人人有份,每个同学手上都有一支笔,自己用自己的,不用再加锁来维持秩序(同步机制是以空间换时间,为每一个线程都提供了一份变量的副本,从而实现同时访问,互不干扰同时访问,肯定效率高啊)



微信图片_20220108142311.png


②. api介绍


①. protected T initialValue():initialValue():返回此线程局部变量的当前线程的"初始值"

(对于initialValue()较为老旧,jdk1.8又加入了withInitial()方法)


②. static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier):创建线程局部变量


③. T get():返回当前线程的此线程局部变量的副本中的值


④. void set(T value):将当前线程的此线程局部变量的副本设置为指定的值


⑤. void remove():删除此线程局部变量的当前线程的值



微信图片_20220108142331.png

微信图片_20220108142350.png


③. 永远的helloword


/***
 * 看每个销售员可以出售多少套房子
 */
class House{
    /**
     initialValue():返回此线程局部变量的当前线程的"初始值"
     对于initialValue()较为老旧,jdk1.8又加入了withInitial()方法
     ThreadLocal<Integer>threadLocal=new ThreadLocal<Integer>() {
         @Override
         protected Integer initialValue() {
             return 0;
         }
     };*/
    //public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier)
    //withInitial(Supplier<? extends S> supplier):创建线程局部变量
    //ThreadLocal本地线程变量,线程自带的变量副本
    ThreadLocal<Integer>threadLocal=
            ThreadLocal.withInitial(()->0);
    public void saleHouse(){
        //T get():返回当前线程的此线程局部变量的副本中的值。
        Integer value = threadLocal.get();
        value++;
        //void set(T value):将当前线程的此线程局部变量的副本设置为指定的值。
        threadLocal.set(value);
    }
}
public class ThreadLocalDemo {
    public static void main(String[] args) {
        House house = new House();
        new Thread(()->{
            try{
                for (int i = 1; i <=3; i++) {
                    house.saleHouse();
                }
                System.out.println(Thread.currentThread().getName()+"\t"+"卖出:"+house.threadLocal.get());
            }catch (Exception e){
                e.getStackTrace();
            }finally {
                //void remove():删除此线程局部变量的当前线程的值
                //在阿里巴巴手册中有说明,尽量在代理中使用try-finally块进行回收
                house.threadLocal.remove();
                //下面获取到的值是线程的初始值0
                System.out.println("**********"+house.threadLocal.get());
            }
        },"t1").start();
        new Thread(()->{
            try{
                for (int i = 1; i <=5; i++) {
                    house.saleHouse();
                }
                System.out.println(Thread.currentThread().getName()+"\t"+"卖出:"+house.threadLocal.get());
            }catch (Exception e){
                e.getStackTrace();
            }finally {
                house.threadLocal.remove();
            }
        },"t2").start();
        new Thread(()->{
            try{
                for (int i = 1; i <=8; i++) {
                    house.saleHouse();
                }
                System.out.println(Thread.currentThread().getName()+"\t"+"卖出:"+house.threadLocal.get());
            }catch (Exception e){
                e.getStackTrace();
            }finally {
                house.threadLocal.remove();
            }
        },"t3").start();
        System.out.println(Thread.currentThread().getName()+"\t"+"卖出了:"+house.threadLocal.get());
    }
}
/**
 * t1 卖出:3
 * t2 卖出:5
 * **********0
 * main 卖出了:0
 * t3 卖出:8
 * */


④. 通过上面代码总结


①. 因为每个Thread内有自己的实例副本且该副本只由当前线程自己使用


②. 既然其他Thread不可访问,那就不存在多线程共享的问题


③. 统一设置初始值,但是每个线程对这个值的修改都是各自线程互相独立的


④. 加入synchronized或者lock控制线程的访问顺序,而ThreadLocal人手一份,大家各自安好,没必要抢夺


相关文章
|
5月前
|
Java 数据库连接
Java中的内存泄漏排查与预防方法
Java中的内存泄漏排查与预防方法
|
24天前
|
监控 JavaScript Java
Node.js中内存泄漏的检测方法
检测内存泄漏需要综合运用多种方法,并结合实际的应用场景和代码特点进行分析。及时发现和解决内存泄漏问题,可以提高应用的稳定性和性能,避免潜在的风险和故障。同时,不断学习和掌握内存管理的知识,也是有效预防内存泄漏的重要途径。
119 52
|
19天前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
39 6
|
5月前
|
缓存 算法 Java
Java面试题:深入探究Java内存模型与垃圾回收机制,Java中的引用类型在内存管理和垃圾回收中的作用,Java中的finalize方法及其在垃圾回收中的作用,哪种策略能够提高垃圾回收的效率
Java面试题:深入探究Java内存模型与垃圾回收机制,Java中的引用类型在内存管理和垃圾回收中的作用,Java中的finalize方法及其在垃圾回收中的作用,哪种策略能够提高垃圾回收的效率
42 1
|
2月前
|
机器学习/深度学习 算法 物联网
大模型进阶微调篇(一):以定制化3B模型为例,各种微调方法对比-选LoRA还是PPO,所需显存内存资源为多少?
本文介绍了两种大模型微调方法——LoRA(低秩适应)和PPO(近端策略优化)。LoRA通过引入低秩矩阵微调部分权重,适合资源受限环境,具有资源节省和训练速度快的优势,适用于监督学习和简单交互场景。PPO基于策略优化,适合需要用户交互反馈的场景,能够适应复杂反馈并动态调整策略,适用于强化学习和复杂用户交互。文章还对比了两者的资源消耗和适用数据规模,帮助读者根据具体需求选择最合适的微调策略。
329 5
|
2月前
|
缓存 监控 Java
在使用 Glide 加载 Gif 动画时避免内存泄漏的方法
【10月更文挑战第20天】在使用 Glide 加载 Gif 动画时,避免内存泄漏是非常重要的。通过及时取消加载请求、正确处理生命周期、使用弱引用、清理缓存和避免重复加载等方法,可以有效地避免内存泄漏问题。同时,定期进行监控和检测,确保应用的性能和稳定性。需要在实际开发中不断积累经验,根据具体情况灵活运用这些方法,以保障应用的良好运行。
|
5月前
|
存储 监控 安全
内存卡数据恢复,3个方法帮你找回丢失的照片和视频
今天,针对内存卡数据恢复,本期做一个详细的归纳,分析常见的数据丢失原因、详细的数据恢复步骤、以及如何保护内存卡数据。
内存卡数据恢复,3个方法帮你找回丢失的照片和视频
|
3月前
|
Java C++
Java内存区域于内存溢出异常
这篇文章详细解释了Java虚拟机的内存区域划分、各区域的作用以及可能遇到的内存溢出异常情况。
52 0
|
4月前
|
存储 Java 编译器
Java内存区域与内存溢出异常 - 运行时数据区
【8月更文挑战第2天】Java运行时数据区包括:1) 程序计数器:记录线程执行字节码的行号,线程私有;2) Java虚拟机栈:描述方法执行的内存模型,线程私有,深度过大抛出`StackOverflowError`;3) 本地方法栈:服务于Native方法,线程私有;4) Java堆:所有线程共享,对象实例在此分配内存;5) 方法区:存储类信息、常量等数据;6) 运行时常量池:方法区的一部分,存放字面量和符号引用。不当使用如无限创建对象或过度递归调用会导致各种内存溢出错误。
|
5月前
|
监控 安全 Java
JVM内存问题之排查Direct Memory泄漏有哪些常用方法
JVM内存问题之排查Direct Memory泄漏有哪些常用方法
155 2