欢迎光临散文网 会员登陆 & 注册

Java常用类库中(ThreadLocal、Comparable比较器、AutoCloseable、Optional空处理)

2023-08-06 10:15 作者:Alphamilk  | 我要投稿

1.ThreadLocal线程独立

如果说每一个用户代表一个线程,那么当用户去访问自己的独有的比如id时候就应该正确返回自己的id。ThreadLocal就好比一个大储物柜里面有许多小的储物柜,每一个线程拥有自己的储物柜,方便自己拿取自己的东西,这样就能保证数据之间的独立与安全

ThreadLocal类常用的方法:

  • T get()返回当前线程关联的变量副本的值。如果没有设置过,则返回null

  • void set(T value)将当前线程关联的变量副本设置为指定的值。

  • void remove()删除当前线程关联的变量副本。

  • protected T initialValue()提供一个初始化值,用于首次访问时创建变量副本的情况。子类可以重写此方法来指定自定义的初始化值。static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier)创建一个带有初始值提供者的ThreadLocal实例。每个线程在首次访问时,都会使用提供者生成一个初始值。

  • static ThreadLocalRandom current()返回当前线程关联的ThreadLocalRandom实例

案例要求:

设置三个线程ABC每一个线程要有独立的资源。并且每个线程输出自己独立的资源

 为什么要用private static final ThreadLocal<Message> ThreadLocal = new ThreadLocal<Message>();static final修饰为了什么目的?

在这段代码中,使用private static final ThreadLocal<Message> ThreadLocal = new ThreadLocal<Message>();ThreadLocal声明为私有静态常量。

private修饰符表示ThreadLocal只能在Channel类内部访问,禁止外部直接访问,从而保证了对ThreadLocal的访问权限的封装性。

static修饰符表示ThreadLocal是一个类级别的变量,而不是实例级别的变量。这意味着所有的Channel实例共享同一个ThreadLocal对象,而不是每个实例都拥有自己的副本。这样做的目的是为了确保线程间的隔离效果。

final修饰符表示ThreadLocal引用的对象是不可变的,一旦引用被赋值,就无法再更改其指向的对象。这里将ThreadLocal声明为常量是为了防止意外修改ThreadLocal的引用,确保程序的稳定性和可靠性。

总的来说,将ThreadLocal声明为private static final的目的是为了实现线程间的资源隔离并确保其访问权限的封装、共享和稳定性。


面试题:ThreadLocal 是什么?有哪些使用场景?

  1. ThreadLocal 是一个本地线程副本变量工具类,在每个线程中都创建了一个 ThreadLocalMap 对象,简单说 ThreadLocal 就是一种以空间换时间的做法,每个线程可以访问自己内部 ThreadLocalMap 对象内的 value。通过这种方式,避免资源在多线程间共享。

  2. 原理:线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。Java提供ThreadLocal类来支持线程局部变量,是一种实现线程安全的方式。但是在管理环境下(如 web 服务器)使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命周期比任何应用变量的生命周期都要长。任何线程局部变量一旦在工作完成后没有释放,Java 应用就存在内存泄露的风险。

  3. 经典的使用场景是为每个线程分配一个 JDBC 连接 Connection。这样就可以保证每个线程的都在各自的 Connection 上进行数据库的操作,不会出现 A 线程关了 B线程正在使用的 Connection; 还有 Session 管理 等问题。

 面试题:请谈谈 ThreadLocal 是怎么解决并发安全的?

  1. 在java程序中,常用的有两种机制来解决多线程并发问题,一种是sychronized方式,通过锁机制,一个线程执行时,让另一个线程等待,是以时间换空间的方式来让多线程串行执行。而另外一种方式就是ThreadLocal方式,通过创建线程局部变量,以空间换时间的方式来让多线程并行执行。两种方式各有优劣,适用于不同的场景,要根据不同的业务场景来进行选择。

  2. 在spring的源码中,就使用了ThreadLocal来管理连接,在很多开源项目中,都经常使用ThreadLocal来控制多线程并发问题,因为它足够的简单,我们不需要关心是否有线程安全问题,因为变量是每个线程所特有的。

面试题: 很多人都说要慎用 ThreadLocal,谈谈你的理解,使用 ThreadLocal 需要注意些什么?

ThreadLocal 变量解决了多线程环境下单个线程中变量的共享问题,使用名为ThreadLocalMap的哈希表进行维护(key为ThreadLocal变量名,value为ThreadLocal变量的值);

使用时需要注意以下几点:

线程之间的threadLocal变量是互不影响的,
使用private final static进行修饰,防止多实例时内存的泄露问题
线程池环境下使用后将threadLocal变量remove掉或设置成一个初始值

2.Comparable比较器与Comparetor

在现实生活中一个班级有很多个人数,也就意味着有许多个对象,如果经历一次考试之后我需要对考试后大家对象数组进行排序,需要成绩从高到低排序,比如黄小龙 成绩总分60 ,蓝小龙 成绩总分50,绿小龙 成绩总分 40等等,可以通过Comparable比较器去设置比较再进行排序

Comparable接口常用的方法

方法描述

  • int compareTo(T other)将当前对象与另一个对象进行比较。返回一个负整数、零或正整数,表示当前对象小于、等于或大于另一个对象。

  • boolean equals(Object obj)检查当前对象是否与另一个对象相等。

  • default Comparator<T> reversed()返回当前比较器的逆序(降序)比较器。默认方法,可以在实现Comparable接口的类中使用。
    default Comparator<T> thenComparing(...)返回一个比较器,该比较器首先使用当前比较器进行比较,然后使用其他指定的比较器进行进一步比较。默认方法,可以在实现Comparable接口的类中使用。

注意:

实现接口需要覆写CompareTo方法,该方法有三个返回值

  • return  1 -->表示结果大于

  • return -1-->表示结果小于

  • return  0 -->表示结果相等

案例要求:经历一场考试后,班级需要对考试班里的同学排名的张贴告示,要求成绩从高到底,每个对象需要有以下信息:名字,学号,成绩总分。以下是本次班级考试结果

张三,210101,560

李四 ,  210108,   589

王五 ,  210116,   340

赵六,   210153,   623

请用数组对象输出成绩从高到低

案例代码:

 注意:Arrays类中引用了Comparable的比较方法CompareTo才能用sort方法

3.AutoCloseable接口

由于资源是有限的,随着程序的扩大对资源越来越多的需求,资源会越来越紧张,所以为了保证资源的合理使用,一些资源使用后就不太需要的时候,就需要进行释放所以引入接口AutoCloseable进行自动的资源释放

AutoCloseable接口的常用方法:

方法描述

  • void close() throws Exception关闭资源的方法,需要在实现类中实现。使用完资源后,应该调用该方法来释放资源。注意,close()方法可能会抛出异常,因此在调用时应该进行异常处理。

  • default void addSuppressed(Throwable exception)将一个异常附加到当前正在关闭的异常上。在关闭资源时,如果出现了其他异常,可以通过该方法将其添加到关闭资源的异常中,以便于统一处理。

  • default void suppressedExceptions(Throwable... exceptions)抑制指定的一组异常。在关闭资源时,如果出现了多个异常,可以通过该方法将它们全部抑制起来。

 案例要求与案例代码:

注意:

要实现自动执行close()方法,可以使用try-with-resources语句块,它会在代码块结束后自动调用资源的close()方法来释放资源。

4.(重点掌握)Optional空处理

在引用对象中存在Null,但是如果调用一个类的静态方法,该方法实现需要一个实例化对象的值,那么此时会出现空异常(NullPointerException)

举个例子

为此Java提供Optional空处理来减少空指针异常的情况

以下是Optional的常用方法

方法描述

  • of(T value)创建一个包含指定非空值的Optional对象

  • ofNullable(T value)创建一个包含指定值的Optional对象,如果值为空,则创建包含空值的Optional对象

  • empty()创建一个空的Optional对象

  • isPresent()判断Optional对象是否包含非空值

  • get()获取Optional对象中的非空值

  • orElse(T other)如果Optional对象中存在非空值,则返回该值;否则返回指定的默认值orElseGet(Supplier<? extends T> otherSupplier)如果Optional对象中存在非空值,则返回该值;否则通过Supplier提供的方法生成并返回默认值

  • orElseThrow(Supplier<? extends X> exceptionSupplier)如果Optional对象中存在非空值,则返回该值;否则根据Supplier提供的方法抛出异常ifPresent(Consumer<? super T> consumer)如果Optional对象中存在非空值,则对该值执行指定操作

  • filter(Predicate<? super T> predicate)如果Optional对象中存在非空值,并且满足指定条件,则返回当前对象;否则返回空的Optional对象

  • map(Function<? super T,? extends U> mapper)如果Optional对象中存在非空值,则对该值应用指定的映射函数,并返回包含映射结果的Optional对象flatMap(Function<? super T,Optional<U>> mapper)如果Optional对象中存在非空值,则对该值应用指定的映射函数,并返回映射结果的Optional对象;否则返回空的Optional对象

 案例代码:


编辑

Java常用类库中(ThreadLocal、Comparable比较器、AutoCloseable、Optional空处理)的评论 (共 条)

分享到微博请遵守国家法律