java - Java单例类和多线程
问题描述
伙计们——我有一个助手类,它的任务是根据参数构建一些消息。该类本身没有任何私有数据(当然实例除外)。
public class RequestBuilder {
private static RequestBuilder instance = new RequestBuilder();
private RequestBuilder() {}
public static RequestBuilder getInstance() {
return instance;
}
public SetRequest buildSetRequest(Path prefix,
Path path,
ConfigEntity configEntity,
Any protoAnyData) {
.....
.....
return setRequest;
}
public GetRequest buildGetRequest(Path prefix,
Path Path,
RetrieveRequestEntity retrieveRequestEntity,
Encoding encoding) {
.....
.....
return getRequest;
}
}
我了解单例类对多线程不友好。在这种情况下,当 2 个线程尝试同时执行 buildSetRequest() 时会发生什么?
谢谢你的时间。
编辑: 根据我的需要,正如@BoristheSpide 在下面的评论中所建议的那样,我将把这个类作为一个实用类进行以下更改: 1. 使其成为最终的。2. 使方法静态化。3. 删除所有单例引用。
public final class RequestBuilder {
private RequestBuilder() {}
public static SetRequest buildSetRequest(Path prefix,
Path path,
ConfigEntity configEntity,
Any protoAnyData) {
.....
.....
return setRequest;
}
public static GetRequest buildGetRequest(Path prefix,
Path Path,
RetrieveRequestEntity retrieveRequestEntity,
Encoding encoding) {
.....
.....
return getRequest;
}
}
我将保留原始代码,因为它仍然有效,并为该问题的评论和答案提供了上下文。
解决方案
在这种情况下,不要太多,因为您的构造函数是空的(其他人提到的没有共享状态)。当您有多个必须初始化的私有实例变量时,问题就开始了。在这种情况下,您需要一些保护,例如 doble-check:
private static volatile RequestBuilder instance;
private RequestBuilder() {}
public static RequestBuilder getInstance() {
if (instance == null) {
synchronized (RequestBuilder.class) {
if (instance == null) {
instance = new RequestBuilder();
}
}
}
return instance;
}
原因是线程可以随时挂起。如果当前构造实例的线程被挂起,而另一个线程来了,则可能有一半初始化的实例变量,并且对象可能最终处于损坏状态。
编辑:关于buildSetRequest()
代码在方法内部,如果该方法自己创建自己的实例或与线程安全类一起使用,则不会有任何问题。
推荐阅读
- spring-boot - 为什么在RestController中Get方法起作用时post方法不起作用?
- python - python 正则表达式替换所有以“:”开头的单词,下一个字符是字母
- jquery - 位置绝对 TD 在可见后留下空白空间
- html - 在引导程序中对齐列
- java - 从内部列表java 8的对象列表中获取ID列表
- c# - 不使用 json.net 从 JSON 字符串获取键值对
- c# - 每次在 AvalonDock 中选择选项卡时重新创建 ViewModel 的视图
- amazon-web-services - 无法在 AWS EC2 实例上模拟 100% 的 CPU 使用率
- android - 将数据从一个屏幕发送到另一个屏幕颤动
- string - Matlab:mapshow和非字符串几何场