如何在Java中返回线程安全/不可变集合?

zw3*_*324 7 java list unmodifiable synchronized thread-safety

在我编写的项目中,我需要从函数返回一个线程安全且不可变的视图.但是,我不确定这一点.由于synchronizedListunmodifiableList刚刚返回视图列表中,我不知道

Collections.synchronizedList(Collections.unmodifiableList(this.data));

会做的伎俩.

任何人都可以告诉我这是否正确,如果不是,是否有任何情况可能会失败?

感谢您的任何投入!

Ray*_*Ray 13

我发现这是JDK中的一个真正的差距.幸运的是,由Java Collections设计师Joshua Bloch领导的Google团队创建了一个包含真正不可变集合的.

ImmutableList尤其是您正在寻找的实现.是Guava的ImmutableCollections的一些功能的快速草图.


duf*_*ymo 5

我认为不可修改就足够了.你不能写它,这是导致多线程访问问题的原因.它是只读的,因此我不需要额外的同步步骤.

如果有这样的问题,最好查看源代码.看起来它返回一个UnmodifiableList:

/**
 * @serial include
 */
static class UnmodifiableList<E> extends UnmodifiableCollection<E>
                  implements List<E> {
    static final long serialVersionUID = -283967356065247728L;
final List<? extends E> list;

UnmodifiableList(List<? extends E> list) {
    super(list);
    this.list = list;
}

public boolean equals(Object o) {return o == this || list.equals(o);}
public int hashCode()       {return list.hashCode();}

public E get(int index) {return list.get(index);}
public E set(int index, E element) {
    throw new UnsupportedOperationException();
    }
public void add(int index, E element) {
    throw new UnsupportedOperationException();
    }
public E remove(int index) {
    throw new UnsupportedOperationException();
    }
public int indexOf(Object o)            {return list.indexOf(o);}
public int lastIndexOf(Object o)        {return list.lastIndexOf(o);}
public boolean addAll(int index, Collection<? extends E> c) {
    throw new UnsupportedOperationException();
    }
public ListIterator<E> listIterator()   {return listIterator(0);}

public ListIterator<E> listIterator(final int index) {
    return new ListIterator<E>() {
    ListIterator<? extends E> i = list.listIterator(index);

    public boolean hasNext()     {return i.hasNext();}
    public E next()          {return i.next();}
    public boolean hasPrevious() {return i.hasPrevious();}
    public E previous()      {return i.previous();}
    public int nextIndex()       {return i.nextIndex();}
    public int previousIndex()   {return i.previousIndex();}

    public void remove() {
        throw new UnsupportedOperationException();
            }
    public void set(E e) {
        throw new UnsupportedOperationException();
            }
    public void add(E e) {
        throw new UnsupportedOperationException();
            }
    };
}
Run Code Online (Sandbox Code Playgroud)

  • 消费者将无法修改列表,但如果保留原始列表,则可以修改原始列表. (3认同)

Awa*_*iru 5

Collections.unmodifiableList(this.data) 
Run Code Online (Sandbox Code Playgroud)

会做,因为它将返回一个视图。对此视图进行任何修改尝试都将导致UnsupportedOperationException抛出该结果。以下是Collections#unmodifiableList文档摘录。

返回指定列表的不可修改视图。此方法允许模块为用户提供对内部列表的“只读”访问权限。对返回列表的查询操作“通读”到指定列表,并尝试直接或通过其迭代器修改返回列表,将导致UnsupportedOperationException。

......

Java 8 java.util.Collections javadoc