我需要一个线程安全的数据结构。我该怎么用?

时间:2018-03-08 15:12:23

标签: java android multithreading concurrency thread-safety

当我使用Retrofit向服务器发送异步调用时,我将此调用放入列表中。

因此,当呼叫状态发生变化(来自服务器的响应或用户取消,......)时,我在列表中添加/删除呼叫。

当进行呼叫并且列表中不存在先前呼叫时,它显示进度对话框。当在列表中删除最后一个调用时,它会关闭该对话框。

那么在这种情况下,哪种数据结构将是最佳选择?我已经看过一些关于java.util.concurrent包的帖子。我确定CopyOnWriteArrayList不是一个好选择,因为我需要频繁地添加/删除数据,但其他呢......目前我使用的是LinkedBlockingQueue。

2 个答案:

答案 0 :(得分:2)

也许尝试使用Collections.newSetFromMap(new ConcurrentHashMap()),因为它可以让你在O(1)附近添加和删除。

答案 1 :(得分:1)

您不仅需要同步数据结构,还需要同步进度对话框实例访问权限。您可以这样同步:

private Object lock = new Object();
private Set<Call> calls = new HashSet<>();
private ProgressDialog progressDialog;

void addCall(Call call) {
    synchronized(lock) {
        calls.add(call);
        if (calls.size() == 1) {
            progressDialog.show();
        }
    }
}

void removeCall(Call call) {
    synchronized(lock) {
        calls.remove(call);
        if (calls.size() == 0) {
            progressDialog.hide();
        }
    }
}

有关同步的更多信息here

谈到性能,这种锁定应该不是问题。如果遇到性能问题,则需要进行调查,找出瓶颈并进行相应修改。请记住,每个线程安全的数据结构都伴随着它自己的开销和权衡。 CopyOnWriteArrayList就是一个很好的例子;在突变方面效率极低,但如果你主要进行遍历则是完美的。