在书中有一个实例,恕我愚钝,不明白这样设计的意图何在:
(例子的背景是:机动车位置追踪)
public class SafePoint{
private int x,y;
private SafePoint(int[] a)
{
this(a[0],a[1]);
}
public SafePoint(SafePoint p)
{
this(p.get())
}public SafePoint(int x,int y)
{
this.x=x;
this.y=y;
}
public synchronized int[] get()
{
return new int[]{x,y}
}
public synchronized void set(int x,int y)
{
this.x=x;
this.y=y;
}书中说:私有的构造方法的存在可以避免一些竞争条件,这些竞争条件会发生在赋值构造函数实现为this(p.x,p.y)的时候,这是私有构造函数捕获模式的实例。问题1:这句话到底是什么什么意思?既然调用构造方法,一定是产生不同的对象实例,为什么还会存在竞争?public class Publishing{
private final Map<String,SafePoint> locations;
private final Map<String,SafePoint> unmodifiableMap;
public Publish(Map<String,SafePoint> locations)
{
this.locations=new ConcurrentHashMap<String,SafePoint>(locations);
this.unmodifiableMap=Collections.unmodifiableMap(this.locations);
}
public Map<String,SafePoint> getLocations()
{
return unmodifiableMap;
}
public SafePoint getLocation(String id)
{
return locations.get(id);
}
....................
}问题2:这里既然locations是ConcurrentHashMap类型,而且是final的,为什么还要将它用Collections.unmodifiableMap(this.locations) 这个包装,为什么不直接返回locations?(当调用public Map<String,SafePoint> getLocations())
unmodifiableMap(this.locations)也是维护的一个final类型的Map。
因为这是大师给的例子,我想一定有他的原因,不是随便弄几个没用的例子上来,所以希望大虾帮我解答一下,谢谢了!
(例子的背景是:机动车位置追踪)
public class SafePoint{
private int x,y;
private SafePoint(int[] a)
{
this(a[0],a[1]);
}
public SafePoint(SafePoint p)
{
this(p.get())
}public SafePoint(int x,int y)
{
this.x=x;
this.y=y;
}
public synchronized int[] get()
{
return new int[]{x,y}
}
public synchronized void set(int x,int y)
{
this.x=x;
this.y=y;
}书中说:私有的构造方法的存在可以避免一些竞争条件,这些竞争条件会发生在赋值构造函数实现为this(p.x,p.y)的时候,这是私有构造函数捕获模式的实例。问题1:这句话到底是什么什么意思?既然调用构造方法,一定是产生不同的对象实例,为什么还会存在竞争?public class Publishing{
private final Map<String,SafePoint> locations;
private final Map<String,SafePoint> unmodifiableMap;
public Publish(Map<String,SafePoint> locations)
{
this.locations=new ConcurrentHashMap<String,SafePoint>(locations);
this.unmodifiableMap=Collections.unmodifiableMap(this.locations);
}
public Map<String,SafePoint> getLocations()
{
return unmodifiableMap;
}
public SafePoint getLocation(String id)
{
return locations.get(id);
}
....................
}问题2:这里既然locations是ConcurrentHashMap类型,而且是final的,为什么还要将它用Collections.unmodifiableMap(this.locations) 这个包装,为什么不直接返回locations?(当调用public Map<String,SafePoint> getLocations())
unmodifiableMap(this.locations)也是维护的一个final类型的Map。
因为这是大师给的例子,我想一定有他的原因,不是随便弄几个没用的例子上来,所以希望大虾帮我解答一下,谢谢了!
public SafePoint(SafePoint p)
{
this(p.get())
}
是一个典型的拷贝构造函数,它为什么没有实现为:
public SafePoint(SafePoint p)
{
this(p.x,p.y)
}是因为这种实现可能会有多线程竞争的风险,因为this(p.x,p.y)由两个赋值语句构成: this.x=x;和this.y=y;如果在执行了第一个语句之后,将要执行第二个语句之时,p的y值被另外一个线程修改了,就会导致对象状态不统一的情况,从而导致拷贝构造函数逻辑失败,所以存在竞争的风险。
而改用get方法则没有此风险的原因是因为get()方法是用synchronized修饰的,锁在对象上的,保证了对象状态的一致性。对于问题2:
为什么要用Collections的unmodifiableMap方法返回一个集合的引用,其实这里跟多线程没有关系,这属于一个良好的集合封装范例:方法不应该直接返回一个集合的引用,而应该返回该集合的不可修改的引用,如果调用者想修改该集合,需要创建另外的方法来修改之。
<重构改善既有代码的设计>一书一节详细阐述了该重构手段,叫:封装集合
public class Test { public List<String> lists = Collections
.synchronizedList(new ArrayList<String>()); public synchronized boolean listIfAbsent(String str) {
boolean ifAbsent = lists.contains(str);
if (!ifAbsent) {
lists.add(str);
}
return ifAbsent;
}
public boolean listIfAbsent1(String str) {
synchronized (lists) {
boolean ifAbsent = lists.contains(str);
if (!ifAbsent) {
lists.add(str);
}
return ifAbsent;
} } public static void main(String[] args) {
final Test t = new Test();
new Thread() {
public void run() {
//该线程正在对list最修改
if (!t.lists.contains("a")) {
t.lists.add("a");
}
if (!t.lists.contains("b")) {
t.lists.add("b");
}
// t.lists.set(0, "chenliang");
System.out.println(t.lists);
}
}.start(); t.listIfAbsent1("a");
// t.listIfAbsent("b"); }
}我就是不明白,直接对lists加锁,和对整个this加锁的区别,this的组成不就是由多个成员变量组成吗?
对this加锁不就是保证了他的数据域不被破坏吗?可是不是这样的,为什么直接锁this和锁成员变量他们用的不是一把锁?
修改的线程和主线程都是操作的一个对象,也就是我标红的部分。为什么会有这样的差异?想不通