Java监视器模式
java监视器模式就是在将共享的数据封装在一个类里面,然后然后所有访问或者修改这些数据的方法都标注为synchronize。
车辆追踪模拟:
使用监视器模式:
CarTracker对象维护了一个所有汽车坐标的Map,这个Map是竞争资源,线程会同时对它进行更新和读取。所以才每个方法上都加了synchronized。
-
package com.zjf;
-
-
import java.util.*;
-
-
//定义坐标
-
class Point{
-
public int x,y;
-
public Point(Point p){
-
this.x=p.x;
-
this.y=p.y;
-
}
-
}
-
-
//车辆追踪
-
public class CarTracker{
-
//维护所有车辆的坐标Map key是汽车的ID 这是竞争资源
-
private Map<String,Point> locations;
-
public CarTracker(Map<String,Point> points){
-
locations=deepCopy(points);
-
}
-
//获得所有车辆的坐标Map
-
public synchronized Map<String,Point> getLocations(){
-
return deepCopy(locations);
-
}
-
//所有某一车辆的坐标
-
public synchronized Point getLocation(String id){
-
Point p=locations.get(id);
-
return (p==null)?null:new Point(p);
-
}
-
//设置某一个汽车的坐标
-
public synchronized void setLocation(String id,int x,int y){
-
Point p=locations.get(id);
-
if(p==null)
-
System.out.print("id not exists");
-
p.x=x;
-
p.y=y;
-
}
-
//深拷贝
-
public static Map<String,Point> deepCopy(Map<String,Point> m){
-
Map<String,Point> result=new HashMap<String,Point>();
-
for(String id:m.keySet()){
-
result.put(id,new Point(m.get(id)));
-
}
-
return Collections.unmodifiableMap(result);
-
}
-
}
使用java的并发集合来重写上面的代码:
-
package com.zjf;
-
-
import java.util.*;
-
import java.util.concurrent.ConcurrentHashMap;
-
import java.util.concurrent.ConcurrentMap;
-
-
//定义坐标 这个是不可变类型 所以可以直接返回 不担心被修改
-
class Point {
-
public final int x, y;
-
public Point(int x, int y) {
-
this.x = x;
-
this.y = y;
-
}
-
}
-
-
// 车辆追踪
-
public class CarTracker {
-
// 维护所有车辆的坐标Map key是汽车的ID 这是竞争资源 使用ConcurrentMap
-
private final ConcurrentMap<String, Point> locations;
-
//是locations的视图 locations的变化会直接映射到这里 但是它是不可修改的。
-
private final Map<String, Point> unmodifiableMap;
-
-
public CarTracker(Map<String,Point> points){
-
locations =new ConcurrentHashMap<String,Point>(points);
-
unmodifiableMap=Collections.unmodifiableMap(locations);
-
}
-
-
// 获得所有车辆的坐标Map 结果是不可修改的
-
public Map<String,Point> getLocations(){
-
return unmodifiableMap;
-
}
-
-
// 获取某一车辆的坐标 结果也是不可修改的
-
public Point getLocation(String id){
-
return locations.get(id);
-
}
-
-
// 设置某一个汽车的坐标 使用replace方法 这是ConcurrentMap提供的并发安全的方法
-
public void setLocation(String id,int x,int y){
-
if(locations.replace(id,new Point(x,y))==null)
-
System.out.print("id not exists");
-
}
-
-
}
上面的方式,我们成为委托。我们把对车辆Map的并发管理委托给ConcurrentHashMap类。