Java并发编程实战 第4章 对象的组合

时间:2023-03-09 22:51:35
Java并发编程实战 第4章 对象的组合

Java监视器模式

java监视器模式就是在将共享的数据封装在一个类里面,然后然后所有访问或者修改这些数据的方法都标注为synchronize。

车辆追踪模拟:

使用监视器模式:

CarTracker对象维护了一个所有汽车坐标的Map,这个Map是竞争资源,线程会同时对它进行更新和读取。所以才每个方法上都加了synchronized。

  1. package com.zjf;
  2. import java.util.*;
  3. //定义坐标
  4.  class Point{
  5.     public int x,y;
  6.     public Point(Point p){
  7.         this.x=p.x;
  8.         this.y=p.y;
  9.     }
  10. }
  11. //车辆追踪
  12. public class CarTracker{
  13.    //维护所有车辆的坐标Map key是汽车的ID 这是竞争资源
  14.     private Map<String,Point> locations;
  15.     public CarTracker(Map<String,Point> points){
  16.         locations=deepCopy(points);
  17.     }
  18.     //获得所有车辆的坐标Map
  19.     public synchronized Map<String,Point> getLocations(){
  20.         return deepCopy(locations);
  21.     }
  22.     //所有某一车辆的坐标
  23.     public synchronized Point getLocation(String id){
  24.         Point p=locations.get(id);
  25.         return (p==null)?null:new Point(p);
  26.     }
  27.     //设置某一个汽车的坐标
  28.     public synchronized void setLocation(String id,int x,int y){
  29.         Point p=locations.get(id);
  30.         if(p==null)
  31.             System.out.print("id not exists");
  32.         p.x=x;
  33.         p.y=y;
  34.     }
  35.     //深拷贝
  36.     public static Map<String,Point> deepCopy(Map<String,Point> m){
  37.         Map<String,Point> result=new HashMap<String,Point>();
  38.         for(String id:m.keySet()){
  39.             result.put(id,new Point(m.get(id)));
  40.         }
  41.         return Collections.unmodifiableMap(result);
  42.     }
  43. }

使用java的并发集合来重写上面的代码:

  1. package com.zjf;
  2. import java.util.*;
  3. import java.util.concurrent.ConcurrentHashMap;
  4. import java.util.concurrent.ConcurrentMap;
  5. //定义坐标 这个是不可变类型 所以可以直接返回 不担心被修改
  6. class Point {
  7.    public final int x, y;
  8.    public Point(int x, int y) {
  9.       this.x = x;
  10.       this.y = y;
  11.    }
  12. }
  13. // 车辆追踪
  14. public class CarTracker {
  15.    // 维护所有车辆的坐标Map key是汽车的ID 这是竞争资源 使用ConcurrentMap
  16.    private final ConcurrentMap<String, Point> locations;
  17.    //是locations的视图 locations的变化会直接映射到这里 但是它是不可修改的。
  18.    private final Map<String, Point> unmodifiableMap;
  19.    public CarTracker(Map<String,Point> points){
  20.         locations =new ConcurrentHashMap<String,Point>(points);
  21.         unmodifiableMap=Collections.unmodifiableMap(locations);
  22.     }
  23.    // 获得所有车辆的坐标Map 结果是不可修改的
  24.    public Map<String,Point> getLocations(){
  25.         return unmodifiableMap;
  26.     }
  27.    // 获取某一车辆的坐标 结果也是不可修改的
  28.    public Point getLocation(String id){
  29.         return locations.get(id);
  30.     }
  31.    // 设置某一个汽车的坐标 使用replace方法 这是ConcurrentMap提供的并发安全的方法
  32.    public void setLocation(String id,int x,int y){
  33.         if(locations.replace(id,new Point(x,y))==null)
  34.             System.out.print("id not exists");
  35.     }
  36. }

上面的方式,我们成为委托。我们把对车辆Map的并发管理委托给ConcurrentHashMap类。