Java 我是否必须将类扩展到ConcurrentHashMap,还是可以使用变量ConcurrentHashMap实现线程安全
我正在创建基于套接字的服务器客户端保留服务,但对于将由多个线程访问的类存在问题,它是否需要扩展ConcurrentHashMap,或者创建变量ConcurrentHashMap就足以保证线程安全 我有两个想法,但我不确定第一个是否可行,因此第一个想法是创建只实现Serializable的类,该类具有变量date,然后是变量ConcurrentHashMap,线程要在其上操作,第二个想法是使用扩展并发哈希映射的类,该类只是CHP,但带有附加变量,以确保它与其他类不同Java 我是否必须将类扩展到ConcurrentHashMap,还是可以使用变量ConcurrentHashMap实现线程安全,java,multithreading,concurrency,java.util.concurrent,concurrenthashmap,Java,Multithreading,Concurrency,Java.util.concurrent,Concurrenthashmap,我正在创建基于套接字的服务器客户端保留服务,但对于将由多个线程访问的类存在问题,它是否需要扩展ConcurrentHashMap,或者创建变量ConcurrentHashMap就足以保证线程安全 我有两个想法,但我不确定第一个是否可行,因此第一个想法是创建只实现Serializable的类,该类具有变量date,然后是变量ConcurrentHashMap,线程要在其上操作,第二个想法是使用扩展并发哈希映射的类,该类只是CHP,但带有附加变量,以确保它与其他类不同 public class Da
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;}
}
公共课日实现可序列化{
私有本地日期;
私有ConcurrentHashMap调度;
公众日(本地日期){
this.date=日期;
this.schedule=新的ConcurrentHashMap();
IntStream.range(10,18).forEachOrdered(
n->this.schedule.put(LocalTime.of(n,0.toString(),TRUE));
}
public void changeaval(字符串键,布尔状态){
本.附表.替换(键、状态);
}
公共布尔值aval(字符串键){
返回此.schedule.get(键);
}
public LocalDate getDate(){返回this.date;}
public ConcurrentHashMap getSchedule(){返回this.schedule;}
}
我只想有一个类/对象,它可以被多个线程访问,可以与其他类/对象区分开来,并且有ConcurrentHashMap,它映射Int->Boolean
这是我第一次使用Stack,这是我在Java中的第一个项目,所以如果有什么不对劲,我不知道该怎么说 基本上,这两种方法是等效的。从体系结构的角度来看,最好在专用类中创建变量,因为可以更好地控制用户可以访问哪些方法。扩展时,用户可以访问基础ConcurrentHashMap的许多方法并滥用它们。处理多线程访问的对象时,基本上需要注意两件事:
Localdate
本身就是一个不可变的线程安全类。如果我们查看这个类的源代码,我们会看到这个类的所有字段都是final
。这意味着只要Localdate
的构造函数完成初始化对象,对象本身就可以在多个线程中看到。但是,当它被分配给不同对象中的引用变量时,我们需要注意的是,分配(换句话说,引用变量的内容)是否对其他线程可见
考虑到您案例中的构造函数,我们可以确保字段date
在线程间的可见性,前提是date
是最终的
或易失性的
。由于您没有修改类中的日期
字段,因此可以很好地将其设置为最终字段,从而确保安全初始化。如果以后决定为该字段使用setter方法(取决于您的业务逻辑和设计),则应使该字段为volatile
,而不是final
volatile
创建“发生在”关系,这意味着在写入volatile
变量之前在特定线程中执行的任何指令,在其他线程读取相同的volatile变量后,都将立即可见
ConcurrentHashMap
也是如此。您应该将字段设置为“明细表”
final
。由于ConcurrentHashMap
本身具有所有必要的同步功能,因此当其他线程尝试读取某个键时,您针对该键设置的任何值都将对其可见
但是,请注意,如果您有一些可变对象作为ConcurrentHashMap
值而不是Boolean
,那么您必须以与上述相同的方式设计它
另外,最好知道有一个称为piggy backing的概念,这意味着如果一个线程写入其所有字段,然后写入volatile
变量,那么在写入volatile
变量之前线程写入的所有内容都将对其他线程可见,假设其他线程在第一个线程写入volatile
变量后第一次读取该变量的值。但是当你这样做的时候,你必须非常小心地确保阅读和写作的顺序,而且很容易出错。因此,当您想要从代码中挤出最后一点性能时,这是很少见的。优先考虑安全性、可维护性和可读性
最后,代码中没有竞争条件。正在进行的唯一写入操作是在
ConcurrentHashMap
上,它本身是线程安全的。感谢您的精彩而全面的回答