gpt4 book ai didi

Java 并发 - 使用哪种技术来实现安全性?

转载 作者:搜寻专家 更新时间:2023-11-01 01:08:50 25 4
gpt4 key购买 nike

我有一个 personId 列表。有两个 API 调用来更新它(添加和删除):

public void add(String newPersonName) {
if (personNameIdMap.get(newPersonName) != null) {
myPersonId.add(personNameIdMap.get(newPersonName)
} else {
// get the id from Twitter and add to the list
}
// make an API call to Twitter
}

public void delete(String personNAme) {
if (personNameIdMap.get(newPersonName) != null) {
myPersonId.remove(personNameIdMap.get(newPersonName)
} else {
// wrong person name
}
// make an API call to Twitter
}

我知道可能存在并发问题。我阅读了 3 种解决方案:

  1. 同步方法
  2. 使用Collections.synchronizedlist()
  3. CopyOnWriteArrayList

我不确定要选择哪个来防止不一致。

最佳答案

1) synchronized the method

2) use Collections.synchronizedlist

3) CopyOnWriteArrayList ..

一切都会起作用,这取决于您需要什么样的性能/功能。

方法#1 和#2 是阻塞方法。如果您同步方法,您自己处理并发。如果将列表包装在 Collections.synchronizedList 中,它会为您处理。 (恕我直言 #2 更安全——只要确保按照文档所说的那样使用它,并且不要让任何东西访问包含在 synchronizedList 中的原始列表。)

CopyOnWriteArrayList是在某些应用程序中使用的那些奇怪的东西之一。它是一个非阻塞的准不可变列表,也就是说,如果线程 A 在线程 B 更改列表时迭代列表,则线程 A 将迭代旧列表的快照。如果您需要非阻塞性能,并且很少写入列表,但经常从列表中读取,那么这也许是最好的选择。


编辑:至少还有两个其他选项:

4) 使用Vector而不是 ArrayListVector 实现了 List 并且已经同步。然而,它通常不受欢迎,因为它被认为是一个老派的类(自 Java 1.0 以来就存在!),并且应该等同于 #2。

5) 仅从一个线程连续访问List。如果这样做,可以保证 List 本身不会出现任何并发问题。一种方法是使用 Executors.newSingleThreadExecutor并逐个排队任务以访问列表。这会将资源争用从您的列表移至 ExecutorService;如果任务很短,可能没问题,但如果有些任务很长,它们可能会导致其他任务的阻塞时间超过预期。

最后,您需要考虑应用程序级别的并发性:线程安全应该是一项要求,并找出如何以尽可能简单的设计获得所需的性能。


附带说明一下,您在 add() 和 delete() 中调用了两次 personNameIdMap.get(newPersonName)。如果另一个线程在每个方法中的两个调用之间修改 personNameIdMap,则会遇到并发问题。你最好还是做

PersonId id = personNameIdMap.get(newPersonName);
if (id != null){
myPersonId.add(id);
}
else
{
// something else
}

关于Java 并发 - 使用哪种技术来实现安全性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6753566/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com