我必须将 class 扩展到 ConcurrentHashMap 还是我可以为 threadSafety 使用变量 ConcurrentHashMap

Do I have to extend class to ConcurrentHashMap or can I have variable ConcurrentHashMap for threadSafety

我正在创建基于 Socket 的服务器-客户端预订服务,并且有关于 class 的问题,它将被多个线程访问,是否需要扩展 ConcurrentHashMap 或创建变量 ConcurrentHashMap 是否足以成为线程安全吗?

我有两个想法,但我不确定第一个是否可行,所以第一个是创建 class,它只实现 Serializable 具有可变日期,然后是线程要在其上运行的变量 ConcurrentHashMap,第二个想法是 class 它扩展了 Concurrent Hash Map 并且只是 CHP,但有附加变量以确保它与其他

区分开来
public class Day implements Serializable {
private LocalDate date;
private ConcurrentHashMap<String, Boolean> schedule;

public Day(LocalDate date){
    this.date = date;
    this.schedule = new ConcurrentHashMap<>();
    IntStream.range(10, 18).forEachOrdered(
            n -> this.schedule.put(LocalTime.of(n, 0).toString(), TRUE));
}

public void changeaval(String key,Boolean status) {
    this.schedule.replace(key,status);
}

public boolean aval(String key){
    return this.schedule.get(key);
}

public LocalDate getDate(){return this.date;}

public ConcurrentHashMap getSchedule(){return this.schedule;}

}

我只想要 Class/Object 可以被多个线程访问并且可以与 others/comparable 区分开来并且具有映射 Int -> Boolean 的 ConcurrentHashMap 这是我第一次使用 Stack,这是我在 Java 中的第一个项目,所以如果有什么不对的地方,我不知道很抱歉。

基本上,这两种方法是等效的。从体系结构的角度来看,在专用 class 中创建变量是首选,因为可以更好地控制用户可以访问哪些方法。扩展时,用户可以访问底层 ConcurrentHashMap 的许多方法并滥用它们。

处理多线程访问的对象时,基本上需要注意两点:

  1. 竞争条件 - 由于操作系统的线程调度和编译器的指令重新排序优化,指令以程序员不希望的顺序执行,导致错误
  2. 内存可见性 - 在多处理器系统中,一个处理器所做的更改并不总是立即对其他处理器可见。出于性能原因,处理器将内容保存在其本地寄存器和缓存中,因此对其他处理器正在执行的线程不可见。

幸运的是,我们可以使用适当的同步处理这两种情况。

让我们谈谈这个特定的程序。

Localdate 本身是一个不可变且线程安全的 class。如果我们查看此 class 的源代码,我们会发现此 class 的所有字段都是 final。这意味着一旦 Localdate 的构造函数完成对象的初始化,对象本身就会跨线程可见。但是当它被赋值给不同对象中的引用变量时,这个赋值(也就是引用变量的内容)是否对其他线程可见是我们需要注意的。

鉴于您的情况下的构造函数,我们可以确保字段 date 跨线程的可见性 provided datefinalvolatile。由于您没有修改 class 中的 date 字段,因此您可以很好地使其成为最终字段并确保安全初始化。如果您稍后决定为该字段使用 setter 方法(取决于您的业务逻辑和您的设计),您应该将字段设置为 volatile 而不是 finalvolatile 创建一个 happens-before 关系,这意味着在写入 volatile 变量之前在特定线程中执行的任何指令将立即对其他线程可见线程一读取相同的 volatile 变量。

ConcurrentHashMap也是如此。您应该使字段 schedule final。由于 ConcurrentHashMap 本身具有所有必要的同步,因此当其他线程尝试读取它时,您针对键设置的任何值都将对它们可见。

但是请注意,如果您有一些可变对象作为 ConcurrentHashMap 值而不是 Boolean,则必须按照上述相同的方式设计它。

另外,知道有一个叫做 piggy-backing 的概念可能会很好,这意味着如果一个线程写入它的所有字段,然后写入一个 volatile 变量,线程在写入 volatile 变量之前写入的所有内容对其他线程都是可见的,前提是其他线程在第一个写入后首先读取 volatile 变量的值线。但是当你这样做的时候,你必须非常小心地确保读写的顺序,而且很容易出错。所以,当你想从一段罕见的代码中挤出最后一滴性能时,就可以这样做。在性能之前优先考虑安全性、可维护性和可读性。

最后,代码中没有竞争条件。唯一发生的写入是在 ConcurrentHashMap 上,它本身是线程安全的。