首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >并发填充线程安全集

并发填充线程安全集
EN

Stack Overflow用户
提问于 2013-05-21 23:02:47
回答 3查看 2.7K关注 0票数 1

假设我有一个线程安全的集合,我将用以下方式填充它:

代码语言:javascript
复制
   Set set = new HashSet();
   for (Map map : maps) {
        set.addAll(doSomeExpensiveProcessing(map.keySet()));
    }

并发执行此操作的最佳方式是什么?(即每个映射将同时将其关键字添加到集合中。

编辑-我知道HashSet不是线程安全的,但就我而言,这超出了问题的范围。

EDIT2 -正确地指出,对于这个特定的场景,并发不会获得巨大的好处,但会有额外的步骤,我现在已经将其包含在代码示例中。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-05-22 00:32:25

虽然@OldCurmudgeon有一个很好的基本方法,但在更严肃的代码中,您可能想要创建一个执行昂贵的键处理的Callable,并返回一个新的Collection。它可以与Executor和/或CompletionService结合使用。最后,您甚至不需要并发收集。

例如,如果键是字符串

代码语言:javascript
复制
public class DoesExpensiveProcessing implements Callable<Set<String>> {

   final Set<String> inKeys;

   public DoesExpensiveProcessing(Set<String> keys) {
     this.inKeys = keys;  // make a defensive copy if required...
   }

   public Set<String> call() {
      // do expensive processing on inKeys and returns a Set of Strings
   }
}

此时,您甚至不需要并行集合

代码语言:javascript
复制
List<DoesExpensiveProcessing> doInParallel = new ArrayList<DoesExpensiveProcessing>();
for (Map map : maps) {
   doInParallel.add(new DoesExpensiveProcessing(map.keySet()));
}

Set theResultingSet = new HashSet<String>();
List<Future<Set<String>>> futures = someExecutorService.invokeAll(doInParallel);
for (Future<Set<String>> f : futures) {
  theResultingSet.addAll(f.get());
}
票数 1
EN

Stack Overflow用户

发布于 2013-05-21 23:09:35

这应该是可行的:

代码语言:javascript
复制
// NB - Be sure to use a concurrent form of Set here.
Set set = new HashSet();
ArrayList<Map> maps = new ArrayList<>();

public void test() {
  for (final Map map : maps) {
    new Thread(new Runnable() {
      @Override
      public void run() {
        set.addAll(map.keySet());
      }
    }).start();
  }
}

我知道您对并发的HashSet实现不感兴趣,但为了完整起见,我想提一下这些选项。

如果您的对象实现了Comparable,那么您可以考虑使用ConcurrentSkipListSet,或者使用Collections.newSetFromMap(new ConcurrentHashMap<Object,Boolean>())

票数 2
EN

Stack Overflow用户

发布于 2013-05-21 23:26:05

这样它就不会并发,但至少threadsafe:

代码语言:javascript
复制
Set set = Collections.synchronizedSet(new HashSet());
...
// in some other threads:
for (Map map : maps) {
  set.addAll(map.keySet());
}

或者你更喜欢下面这样的东西:

代码语言:javascript
复制
ConcurrentMap<Object, Boolean> set = new ConcurrentHashMap<Object, Boolean>();
...
// in some other threads:
for (Map map : maps) {
  for (Object o : map.keySet()) {
    set.putIfAbsent(o, true);
  }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16673267

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档