gpt4 book ai didi

java - 保证在多线程环境中迭代所有值

转载 作者:行者123 更新时间:2023-12-02 11:00:27 25 4
gpt4 key购买 nike

我有一个Set具有任何类型的值和 AtomicBoolean指示该类提供的功能是否正在运行。

private Set<Object> set = new HashSet<>();
private AtomicBoolean running;

现在,我有两种方法,其中一种是将对象添加到集合中,另一种用作我的类的设置方法。

public void start() {
// ...

set.foreEach(someApi::addObject);

// ...
running.set(true);
}

public void addObject(Object o) {
set.add(o);
if(running.get()) {
someApi.addObject(o);
}
}

但是,该代码有一个问题。如果该方法是从另一个线程调用的,而start方法正在迭代集合 running仍然是false 。因此,该对象不会添加到 api。

问题:我如何保证集合中的所有对象以及添加 addObject 的对象是否会被添加到 api 一次?

我的想法:

  • 使用锁并阻止addObject method 如果安装程序当前正在向 api 添加方法(或者使这两个方法都为 synchronized ,这会稍微降低性能)

最佳答案

Question: How can i guarantee that all objects in the set and objects added with addObject will be added to the api exactly one time?

这里你必须小心,因为这接近 ole "double check locking bug" .

如果我理解你的问题,你想:

  1. 在调用 start() 之前,将传入 addObject(...) 的对象放入集合中。
  2. 然后,当调用 start() 时,对集合中的对象调用 API 方法。
  3. 如果在调用 start() 期间添加了其他对象,则处理重叠
  4. 对传递给 addObject(...) 的所有对象调用该方法一次且仅一次。

令人困惑的是您的 API 调用也被命名为 addObject()。我认为这与代码示例中的 addObject(...) 方法不同。我将在下面将其重命名为 someApiMethod(...) 以表明它不会递归。

不幸的是,最简单的方法是在每个方法中都有一个 synchronized block :

private final Set<Object> set = new HashSet<>();
public void start() {
synchronized (set) {
set.forEach(someApi::someApiMethod);
}
}
public void addObject(Object obj) {
synchronized (set) {
if (set.add(obj)) {
someApi.addObject(obj);
}
}
}
}

为了使其更快,需要使用更复杂的代码。您可以做的一件事是使用 ConcurrentHashMap 和 AtomicBoolean running 。像这样的东西:

private final ConcurrentMap<Object, Object> map = new ConcurrentHashMap<>();
private final Set<Object> beforeStart = new HashSet<>();
private final AtomicBoolean running = new AtomicBoolean();
public void start() {
synchronized (beforeStart) {
for (Object obj : beforeStart) {
doIfAbsent(obj);
}
running.set(true);
}
}
public void addObject(Object obj) {
if (running.get()) {
doIfAbsent(obj);
} else {
synchronized (beforeStart) {
// we have to test running again once we get the lock
if (running.get()) {
doIfAbsent(obj);
} else {
beforeStart.add(obj);
}
}
}
}
private void doIfAbsent(Object obj) {
if (map.putIfAbsent(obj, obj)) {
someApi.someApiMethod(obj);
}
}

这非常复杂,并且可能不会更快,具体取决于您的 HashMap 有多大和其他因素。

关于java - 保证在多线程环境中迭代所有值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51370387/

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