【问题标题】:A unsychronized Collection object that contain some data, want synchronisation wrapper but don't want reference to original object包含一些数据的未同步集合对象,需要同步包装但不希望引用原始对象
【发布时间】:2017-03-06 05:39:27
【问题描述】:

我目前在Java tutorial oracle上学习Java Collections,遇到了下面这段

这些方法中的每一个都返回由指定集合备份的同步(线程安全)Collection。为了保证串行访问,必须通过返回的集合完成对支持集合的所有访问。保证这一点的简单方法是不保留对支持集合的引用。使用以下技巧创建同步集合。

List<Type> list = Collections.synchronizedList(new ArrayList<Type>());

我只是想知道,如果我有一个未同步的 Collection 实例(支持集合)并且包含一些数据,我想将这个 Collection 实例(支持支持集合)到一个同步集合中,但不想保留对支持集合的引用。怎么可能做到这一点?是否可以?如果是,这是人们通常会做的事情吗?

【问题讨论】:

  • 如果您打算更改集合的状态,为什么不先复制它?
  • 当然,您可以包装现有的集合。 最好不要持有对支持集合的引用,因为这样可以确保它不会被意外修改。
  • 你的问题不清楚..你可以得到一个新的列表并轻松转储旧的列表

标签: java collections synchronization


【解决方案1】:

为了保证您不保留对支持集合的引用,请退出您的引用范围。

换句话说,在块内声明对支持数组的引用,并确保将引用传递给Collections.synchronizedList() 方法。退出该块时,引用将丢失,您可以确定只有同步包装器引用了支持集合。

这不是一种常见的方法,但只要在包装后不对支持集合进行任何更改,它就不会导致并发问题。但是,这可能会引起您的同事的一些争论,他们知道引用的成语是安全的,但不确定您的创新。仅此一项就足以成为通过包装而不是支持集合添加元素的充分理由。

这是一个例子:

class MyObj {

  private final List<Type> list;

  MyObj(/* Some arguments that control initial list contents */) {
    List<Type> tmp = new ArrayList<>();
    tmp.add(...);
    list = Collections.synchronizedList(tmp);
  } /* Reference to `tmp` is lost, safety is ensured. */

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-31
    • 1970-01-01
    • 2015-08-29
    • 1970-01-01
    • 2013-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多