Collections.synchronizedList 工厂方法
通常的Map,Set,List实现都不是线程安全的,通过这些工厂方法可以得到相应的同步容器,相当于增强了访问控制,把一个链表对象传递过来后,我们都通过返回的这个链表对象来进行各种操作(都是同步方法),而不再操纵底层的那个链表。此外,在Vector和同步封装器类中是用内置锁来来支持客户端加锁,所以我们可以进行扩展。
在对对链表迭代的过程中也要注意加锁,否则在迭代的过程中,如果其他某个线程改变了容器的属性,next,hasNext方法就会抛出ConcurrentModificationException 异常(而诸如ConcurrentHashMap的并发容器不需要迭代过程加锁)。更重要的是,要防止隐藏迭代,如果对某个容器调用toString方法的时候。下面是对应的代码。
1.迭代的时候要同步。
List<Integer> safeList = Collections. synchronizedList(
new
ArrayList<Integer>());
synchronized
(safeList) {
Iterator<Integer> i = safeList.iterator();
// Must be in synchronized block
while
(i.hasNext())
System.
out
.println(i.next());
}
2.隐藏迭代器。
public
class
HiddenIterator {
private
final
Set<Integer>
set
=
new
HashSet<Integer>();
public
synchronized
void
add(Integer i) {
set
.add(i);
}
public
synchronized
void
remove(Integer i) {
set
.remove(i);
}
public
void
addTenThings() {
Random r =
new
Random();
for
(
int
i = 0; i < 10; i++)
add(r.nextInt());
System.
out
.println(
"DEBUG: added ten elements to "
+
set
);
//这里
}
}
2.容器中toString方法的实现。
public
String toString() {
Iterator<E> it = iterator();
if
(! it.hasNext())
return
"[]"
;
StringBuilder sb =
new
StringBuilder();
sb.append(
'['
);
for
(;;) {
E e = it.next();
sb.append(e ==
this
?
"(this Collection)"
: e);
if
(! it.hasNext())
return
sb.append(
']'
).toString();
sb.append(
','
).append(
' '
);
}
}