Java并发 - 使用哪种技术来实现安全性? [英] Java concurrency - use which technique to achieve safety?

查看:142
本文介绍了Java并发 - 使用哪种技术来实现安全性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a list of personId. There are two API calls to update it (add and remove):

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个解决方案:

I know there can be concurrency problem. I read about 3 solutions:


  1. synchronized 方法

  2. 使用 Collections.synchronizedlist()

  3. CopyOnWriteArrayList

  1. synchronized the method
  2. use Collections.synchronizedlist()
  3. CopyOnWriteArrayList

我不确定是谁h喜欢防止不一致。

I am not sure which one to prefer to prevent the inconsistency.

推荐答案


1)同步方法

1) synchronized the method

2)使用Collections.synchronizedlist

2) use Collections.synchronizedlist

3)CopyOnWriteArrayList ..

3) CopyOnWriteArrayList ..

一切都会有效,这取决于你需要什么样的性能/功能。

All will work, it's a matter of what kind of performance / features you need.

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

Method #1 and #2 are blocking methods. If you synchronize the methods, you handle concurrency yourself. If you wrap a list in Collections.synchronizedList, it handles it for you. (IMHO #2 is safer -- just be sure to use it as the docs say, and don't let anything access the raw list that is wrapped inside the synchronizedList.)

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

CopyOnWriteArrayList is one of those weird things that has use in certain applications. It's a non-blocking quasi-immutable list, namely, if Thread A iterates through the list while Thread B is changing it, Thread A will iterate through a snapshot of the old list. If you need non-blocking performance, and you are rarely writing to the list, but frequently reading from it, then perhaps this is the best one to use.

编辑至少还有两个选项:

4)使用 Vector ArrayList ; Vector 实现 List 并且已经同步。然而,它通常是皱眉头,因为它被认为是一个老派班级(自Java 1.0以来就在那里!),应该相当于#2。

4) use Vector instead of ArrayList; Vector implements List and is already synchronized. However, it's generally frowned, upon as it's considered an old-school class (was there since Java 1.0!), and should be equivalent to #2.

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

5) access the List serially from only one thread. If you do this, you're guaranteed not to have any concurrency problems with the List itself. One way to do this is to use Executors.newSingleThreadExecutor and queue up tasks one-by-one to access the list. This moves the resource contention from your list to the ExecutorService; if the tasks are short, it may be fine, but if some are lengthy they may cause others to block longer than desired.

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

In the end you need to think about concurrency at the application level: thread-safety should be a requirement, and find out how to get the performance you need with the simplest design possible.

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

On a side note, you're calling personNameIdMap.get(newPersonName) twice in add() and delete(). This suffers from concurrency problems if another thread modifies personNameIdMap between the two calls in each method. You're better off doing

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

这篇关于Java并发 - 使用哪种技术来实现安全性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆