在Java中同时检查重复项并将项目添加到列表/集合中

24 浏览
0 Comments

在Java中同时检查重复项并将项目添加到列表/集合中

我有一些代码正在通过启动多个线程并以给定速率向服务发送指定事务来对一个Web服务进行负载测试。该事务从服务中检索一个值列表,然后检查这个值列表是否存在于一个集合中,如果不存在就将其添加进去,如果存在则事务失败(我知道不需要进行额外的检查,并且可以检查添加的返回值-这只是现在代码的写法)。\n然而,看着这段代码,它并不是线程安全的。被检查/添加的集合是一个基本的HashSet。当前的代码还会对一个常规的HashMap中的值进行递增操作-所以从一开始看,这段代码在处理线程安全方面就有问题了。\n我相信我已经通过使用基于ConcurrentHashMap的解决方案解决了Map递增问题:Atomically incrementing counters stored in ConcurrentHashMap,但是我不确定以线程安全的方式处理Set上的重复检查/修改的最佳方法。\n最初,我考虑使用CopyOnWriteArraySet,但由于期望的情况是不会出现重复值,读操作会和写操作同频率发生,所以这似乎不是理想的解决方案。我现在考虑的解决方案是使用ConcurrentHashMap上的Set“视图”,使用newKeySet()/KeySet(defaultVal)来实现,参考:https://javarevisited.blogspot.com/2017/08/how-to-create-thread-safe-concurrent-hashset-in-java-8.html\n如果我使用这个解决方案,通过添加值并检查布尔返回类型来检查重复值,这样做是否能以线程安全的方式实现我的目标?我最关心的是能够正确检测到任何重复值。我不希望发生的情况是两个线程尝试同时添加,两个添加都返回true,因为当它们尝试添加时值不在那里,并且从服务中接收到的重复值未被检测到。为了这个目的,我想也许我应该使用一个List,在最后将其转换为Set并检查大小来检查重复值?但是,在事务期间至少尝试检测到重复值并在检测到时失败仍然更好。如果我们最后可以检测到,即使有时会得到错误的结果,事务仍然可以通过。但是我认为在我们能够检测到时进行检查/失败的事务仍然是有价值的。\n感谢您提供的任何建议!

0
0 Comments

同时检查重复项并将项添加到Java中的列表/集合的问题的原因是希望避免向列表/集合中添加重复的项。解决方法有多种,具体如下:

1. 如果事务对象(或者您放入Set中的任何对象)已经正确实现了equals方法,您就不需要在Set中检查重复项。因为Set总是只包含唯一的值。如果您仍然需要知道对象是否已经在集合中,可以使用contains方法。

2. 您可以使用ConcurrentHashMap代替Set,将您的对象作为键放入其中。在ConcurrentHashMap中,您可以使用keySet方法获取键集合,并进行相关操作。值可以是任何类型(例如相同的对象)。当然,您也可以使用valueSet。

3. 您可以使用其中一种BlockingQueue(例如LinkedBlockingQueue)实现来首先从不同的线程中收集事务,然后在所有线程完成后应用任何您想要的逻辑。

当然,还有许多其他方法可以解决这个问题。

0
0 Comments

并发检查重复项并将项添加到列表/集合的问题常常出现在需要在多个线程中同时进行数据操作的情况下。在Java中,可以使用ConcurrentHashMap和ConcurrentHashSet来解决这个问题。

ConcurrentHashMap是Java中的一个线程安全的哈希表实现,它提供了高效的并发访问和更新操作。ConcurrentHashMap.newKeySet()方法返回一个ConcurrentHashSet,该集合是基于ConcurrentHashMap实现的,因此可以同时获得线程安全和高性能。

下面是使用ConcurrentHashSet解决并发检查重复项并将项添加到列表/集合的示例代码:

Set<Value> values = ConcurrentHashMap.newKeySet();

通过使用这个ConcurrentHashSet,我们可以在多个线程中同时执行添加操作,而无需担心线程安全问题。ConcurrentHashSet内部使用ConcurrentHashMap来确保多线程访问时的安全性和一致性。

这种解决方案的好处是,它不仅提供了线程安全性,还能在并发操作中保持较高的性能。这是因为ConcurrentHashMap和ConcurrentHashSet的内部实现使用了一些高效的并发控制技术,如锁分段和CAS操作。

因此,如果你需要在多个线程中同时检查重复项并将项添加到列表/集合中,可以考虑使用ConcurrentHashSet来解决这个问题。它能够提供高效的并发访问和更新操作,同时保证线程安全性。

0
0 Comments

这个问题的原因是作者想要在Java中同时检查重复项并将项添加到列表或集合中,但不确定如何以线程安全的方式处理重复检查和修改问题。

解决方法是使用ConcurrentHashMap类来解决Map增量问题,并使用该类的putIfAbsent(...)方法来实现线程安全的重复检查和修改。

ConcurrentHashMap是一个完全可重入的类,所以如果两个线程在同一时刻进行相同的key的put(...)操作,其中一个线程会成功并返回现有的key的null值,而另一个线程会替换该key并返回之前的值,这样你就可以进行测试。ConcurrentHashMap专门为高性能多线程应用程序设计。如果你使用keyset包装器来提供Set机制,你也可以使用putIfAbsent(...)方法。

但是在使用同步类时,需要注意在多次调用类时自己代码中的竞争条件。在上面的代码示例中,多次调用并发映射会导致竞争条件。为了解决这个问题,ConcurrentMap提供了一些原子操作:

- putIfAbsent(K key, V value),如果key不存在,则将key放入映射中

- remove(K key, V value),如果key具有指定的value,则从映射中删除key

- replace(K key, V oldValue, V newValue),只有在key已经具有oldValue的情况下,才使用newValue替换key

- replace(K key, V value),只有在映射中已经存在key的情况下,才替换与key关联的值

所有这些方法都需要在外部对同步映射进行多次非原子调用来实现,这将引入竞争条件。

关于重复项检测的问题,不需要担心两个线程同时尝试添加重复项的情况。如上所述,其中一个put操作将返回null,而另一个应该被视为重复项。

关于使用列表并在最后通过转换为集合并检查大小来检查重复项的想法是不必要的,而且很难正确实现。

0