Java监视器模式

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

车辆追踪模拟:

使用监视器模式:

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

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

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

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

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

Java并发编程实战 第4章 对象的组合的更多相关文章

  1. Java并发编程实战 第3章 对象的共享

    可见性 可见性是由于java对于多线程处理的内存模型导致的.这似乎是一种失败的设计,但是JVM却能充分的利用多核处理器的强大性能,例如在缺乏同步的情况下,Java内存模型允许编译器对操作顺序进行重排序 ...

  2. 【JAVA并发编程实战】2、对象的组合

    1. 设计线程安全的类 1.找出构成对象状态的所有变量 2.找出约束状态变量的不变性条件 3.建立对象状态的并发访问管理策略 package cn.xf.cp.ch04; /** * *功能:JAVA ...

  3. Java并发编程实战---第六章:任务执行

    废话开篇 今天开始学习Java并发编程实战,很多大牛都推荐,所以为了能在并发编程的道路上留下点书本上的知识,所以也就有了这篇博文.今天主要学习的是任务执行章节,主要讲了任务执行定义.Executor. ...

  4. Java并发编程实战 第16章 Java内存模型

    什么是内存模型 JMM(Java内存模型)规定了JVM必须遵循一组最小保证,这组保证规定了对变量的写入操作在何时将对其他线程可见. JMM为程序中所有的操作定义了一个偏序关系,称为Happens-Be ...

  5. 【java并发编程实战】第一章笔记

    1.线程安全的定义 当多个线程访问某个类时,不管允许环境采用何种调度方式或者这些线程如何交替执行,这个类都能表现出正确的行为 如果一个类既不包含任何域,也不包含任何对其他类中域的引用.则它一定是无状态 ...

  6. Java并发编程实战 第8章 线程池的使用

    合理的控制线程池的大小: 下面内容来自网络.不过跟作者说的一致.不想自己敲了.留个记录. 要想合理的配置线程池的大小,首先得分析任务的特性,可以从以下几个角度分析: 任务的性质:CPU密集型任务.IO ...

  7. 读书笔记-----Java并发编程实战(二)对象的共享

    public class NoVisibility{ private static boolean ready; private static int number; private static c ...

  8. JAVA并发编程实战---第三章:对象的共享(2)

    线程封闭 如果仅仅在单线程内访问数据,就不需要同步,这种技术被称为线程封闭,它是实现线程安全性的最简单的方式之一.当某个对象封闭在一个线程中时,这种方法将自动实现线程安全性,即使被封闭的对象本生不是线 ...

  9. JAVA并发编程实战---第三章:对象的共享

    在没有同步的情况下,编译器.处理器以及运行时等都可能对操作的执行顺序进行一些意想不到的调整.在缺乏足够同步的多线程程序中,要对内存操作的执行顺序进行判断几乎无法得到正确的结果. 非原子的64位操作 当 ...

随机推荐

  1. XAMPP安装后启动Apache的Busy解决方法

    启动apache后,一直提示80 busy 使用netstat -ano查看,并无端口占用,真是奇怪. 百度之后发现有可能是启动后,ssl端口占用导致. XAMPP默认会加载一个SSL模块,它要占用一 ...

  2. Jmeter(九)集合点

    性能测试需要模拟大量用户并发,集合点能够尽量让虚拟用户同一时刻发送请求, 在Jmeter中集合点是通过定时器-同步定时器来完成的.

  3. ElasticSearch第五步-.net平台下c#操作ElasticSearch详解

    前面我们讲解了关于ElasticSearch的安装配置,以及CRUD 本章我将讲解怎么使用c#操作ElasticSearch. 首先你需要一定的技术储备,比如:asp.net webapi,mvc,j ...

  4. Python实现打印螺旋矩阵功能的方法

    Python实现打印螺旋矩阵功能的方法 本文实例讲述了Python实现打印螺旋矩阵功能的方法.分享给大家供大家参考,具体如下: 一.问题描述 输入N, 打印 N*N 螺旋矩阵 比如 N = 3,打印: ...

  5. poatman接口测试--初试

    接到测试任务,对两个商品接口,进行接口测试 测试工具:postman 域名:rap2查找的或询问开发, 接口的参数规则:参考rap2的备注 开发没有添加详细说明的,让开发补充说明规则,及定义的返回状态 ...

  6. IDEA 对spring boot Maven 项目打 Jar 包

    <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> ...

  7. PMP项目正常估算时间

    最佳时间段+正常时间段*+最差时间段)/=正常估算时间. 项目经理小李对某活动工期进行估算时,发现人员的熟练程度和设备供应是否及时对工期至关重要.如果形成最有利组合时,预计17天可以完成:如果形成最不 ...

  8. 小记-----如何把本地jar包加载到maven库中

    1.从maven中央库下载下jar包

  9. Anaconda配置环境变量+创建虚拟环境+pycharm使用虚拟环境

    Anaconda配置环境变量+创建虚拟环境 配置环境变量 没有添加系统变量,所有系统根本识别不了conda命令,找不到位置,所以添加以下系统变量: 添加对应Anaconda环境变量:(以自己的安装路径 ...

  10. SPOJ 4003 Phone List 题解

    题面 啊~,很水的一道trie树模板题: 当两个串存在关系时情况有两种: 若当前串插入后没有任何新建节点,则该串肯定是之前插入的某个串的前缀: 若在插入的时候,有某个经过的节点带有某串结尾的标记,则之 ...