我有几个关于多线程的问题(我想安全快速地完成我的小项目)。
我有一个类库。我会将用户请求添加到一个文件中。
public static volatile HashMap<String, GooglePlayGame> games = new HashMap<>(500);在每次应用启动时,我都会在静态块中使用一个文件(json+Jackson)来初始化这个哈希图:
static {
TypeFactory typeFactory = mapper.getTypeFactory();
MapType mapType = typeFactory.constructMapType(HashMap.class, String.class, GooglePlayGame.class);
try {
games = mapper.readValue(new File("games.json"), mapType);
} catch (IOException e) {
log.error(e.getMessage());
}
}每个用户的请求(使用特殊命令/library)将被处理,然后新的“键-值”对将被添加到全局哈希图中,当然,如果键不存在(用containsKey检查)。然后使用这个hashmap (而不是从文件)。
然后我想把新的配对写入我的文件中。为此,我想创建一个新线程,如下所示:
Thread thread = new Thread(() -> {
try {
mapper.writeValue(new File("games.json"), games);
} catch (IOException e) {
e.printStackTrace();
}
});
thread.start();问题:
1)“易失性”有帮助吗?它是否保证在写入文件时,我将始终看到所有最后添加的对?
2)如果..不是每对新的写入文件,而是每10对写入文件?该怎么做呢?使用CountDownLatch?如果是,如何正确组织这一点?我不太擅长多线程。但是如果程序崩溃了,我收到了9个新的请求,这些请求对就会丢失!
3)顺便问一下,我是在这里创建一个新文件,还是只是覆盖旧文件?如果我总是创建新文件,这就有点糟糕了。杰克逊在创建新文件还是覆盖旧文件?
发布于 2020-03-20 18:40:20
1)在这种情况下,volatile关键字不会给你想要的东西。当你搜索它所做的事情时,它可能会有一点误导。你可以发现"volatile关键字保证了对变量的所有写操作对所有线程都是可见的“。它的意思是,当你给变量分配一个新的值(新对象)时,它将是可见的。但是,如果更改了分配给该变量的对象,则这些更改不一定对所有线程都可见。
在本例中,您修改的是Hashmap,而不是变量,因此它可能不可见。您应该考虑使用一些线程安全的专用内置集合,如ConcurrentHashMap
2)你不能确保所有的数据都会在崩溃的情况下写入文件。在每次输入之后写入数据总是更安全的,但这取决于它发生的频率。如果是一分钟一次,那么一次写1也没问题,如果是每秒几千次,那么你应该考虑批量写入。
3)我认为自己测试它应该很容易。此外,它与主要问题并不相关,主要问题是关于多线程的。
发布于 2020-03-20 20:49:22
以下是您使用volatile关键字的主要原因:
如果你有一些volatile ... x;,那么在线程B观察到分配之后,线程A在分配x = v;之前所做的任何事情对线程B都是可见的。
final XType v = ...;
volatile XType x = ...some value other than v...;
AType a;
BType b;
CType c;在线程A中:
a = ...;
b = ...;
x = v;
c = ...;在线程B中:
while (x != v) {
...sleep, or spin, or maybe do some useful work...
}
...guaranteed to see the new values of a, and b here.
...No guarantee about c. Could see the old value or the new value.但请注意!触发该行为的是赋值x = v;
您的程序初始化volatile变量games,但是您的程序没有指定games的位置。程序中的任何东西都不会触发games的易失性。关键字在您的特定示例中不起作用。
https://stackoverflow.com/questions/60772230
复制相似问题