【JAVA并发编程实战】2、对象的组合
1、 设计线程安全的类
1、找出构成对象状态的所有变量
2、找出约束状态变量的不变性条件
3、建立对象状态的并发访问管理策略
package cn.xf.cp.ch04; /**
*
*功能:JAVA监视器模式的线程安全计数器
*时间:下午6:22:23
*文件:Counter.java
*@author Administrator
*
*/
public class Counter
{
//只有这一个变量,这个value就是counter的全部状态
private long value = 0; //获取值,单线程操作
private synchronized long getValue()
{
return value;
} public synchronized long increment()
{
if(value == Long.MAX_VALUE)
throw new IllegalStateException("统计数值溢出");
return ++value;
}
}
2、实例封闭
将数据封装在对象内部,可以将数据的访问限制在对象的方法上,从而更容易确保线程在访问数据时总能持有正确的锁。
通过封闭与加锁等机制使一个类成为线程安全的
package cn.xf.cp.ch04; public class Person
{
private String name;
private int age;
private char sex;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public char getSex()
{
return sex;
}
public void setSex(char sex)
{
this.sex = sex;
} }
package cn.xf.cp.ch04; import java.util.HashSet;
import java.util.Set; public class PersonSet
{
private final Set<Person> mySet = new HashSet<Person>(); public synchronized void addPerson(Person p)
{
mySet.add(p);
} public synchronized boolean containsPerson(Person p)
{
return mySet.contains(p);
}
}
2、1 Java监视器模式
这个模式的对象会把所有可变状态都封装起来,并由对象自己的内置锁来保护。
package cn.xf.cp.ch04; /**
*
*功能:私有锁的使用
*时间:下午9:18:01
*文件:PrivateLock.java
*@author Administrator
*
*/
public class PrivateLock
{
//使用私有变量作为对象锁
private final Object myLock = new Object();
private int i; public void someMethod()
{
synchronized(myLock)
{
//这里对状态量i进行操作
i = 110;
System.out.println("私有锁");
}
}
}
私有的锁对象可以将锁封装起来,使客户代码无法获取锁,但是客户代码可以通过公有方法来访问锁,这样也就可以参与到同步中来。
活跃性的问题:死锁, 饥饿和活锁
饥饿(Starvation)
它描述了这样一个场景,当一个线程不能获取定期访问来共享资源而不能继续运行,在共享资源被饥渴线程长期占有时,就会发生饥饿。例如,加速一个对象提供一个要花很长时间才能返回结果的同步方法,如果一个线程频繁调用这个方法,其它线程也需要频繁调用同步进入同一个对象的方法时,阻塞就发生了。
活锁(Livelock)
一个线程经常对另外一个线程的响应做响应的处理,如果线程的另外一个动作同样是对另外一个线程响应而发生,结果可能导致活锁,类似死锁,发生活锁的线程不能更进一步的处理,然而,线程并没有被阻塞,他们只是忙碌于响应对方而重复工作,这类似于两个人在走廊中试图让对方,a移向左以让b通过,而b移向右以让a通过,可以看到,他们仍然互相阻塞,a移动到右边,而b移动到左边,结果他们仍然还是阻塞着。。。
如果不使用私有锁:那么可能客户代码错误地获取另一个对象的锁,可能会产生活跃性的问题(一个并发应用能够及时执行任务的特性称为活跃性)。此外想要验证某个公有访问的锁在程序中是否被正确地使用,则需要检查整个程序,而不是单个类。
2、2 示例:车辆追踪
车辆标识和位置点,类型
package cn.xf.cp.ch04; public class MutablePoint
{
private int x, y; public MutablePoint()
{
x = 0;
y = 0;
} public MutablePoint(MutablePoint p)
{
this.x = p.getX();
this.y = p.getY();
} public synchronized int getX()
{
return x;
} public synchronized void setX(int x)
{
this.x = x;
} public synchronized int getY()
{
return y;
} public synchronized void setY(int y)
{
this.y = y;
}
}
车辆追踪类
package cn.xf.cp.ch04; import java.util.Collections;
import java.util.HashMap;
import java.util.Map; /**
*
*功能:基于监视器模式的车辆追踪
*时间:下午9:50:12
*文件:MonitorVehicleTracker.java
*@author Administrator
*
*/
public class MonitorVehicleTracker
{
private final Map<String, MutablePoint> locations; //构造函数对map进行初始化
public MonitorVehicleTracker(Map<String, MutablePoint> locations)
{
//为了保持内部数据不会发生逸出,进行深拷贝
this.locations = deepCopy(locations);
} public synchronized Map<String, MutablePoint> getLocations()
{
return deepCopy(locations);
} public synchronized MutablePoint getLocation(String id)
{
//获取要返回的数据
MutablePoint loc = locations.get(id);
//创建一个新的对象返回
return loc == null ? null : new MutablePoint(loc);
} public synchronized void setLocation(String id, int x, int y)
{
MutablePoint loc = locations.get(id);
if(loc == null)
{
//如果没有这个对象的话,抛出异常,还是重新创建,看个人业务
throw new IllegalArgumentException("没有这个id:" + id);
}
loc.setX(x);
loc.setY(y);
} private static Map<String, MutablePoint> deepCopy(Map<String, MutablePoint> m)
{
//创建一个新的接受数据对象
Map<String, MutablePoint> result = new HashMap<String, MutablePoint>();
//循环取数据
for(String id : m.keySet())
{
//根据key取值
result.put(id, m.get(id));
} //返回数据,返回指定映射的不可修改视图。
//此方法允许模块为用户提供对内部映射的“只读”访问
return Collections.unmodifiableMap(result);
}
}
【JAVA并发编程实战】2、对象的组合的更多相关文章
- Java并发编程实战 之 对象的共享
上一篇介绍了如何通过同步多个线程避免同一时刻访问相同数据,本篇介绍如何共享和发布对象,使它们被安全地由多个进程访问. 1.可见性 通常,我们无法保证执行读操作的线程能看到其他线程写入的值,因为每个线程 ...
- 《Java并发编程实战》/童云兰译【PDF】下载
<Java并发编程实战>/童云兰译[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062521 内容简介 本书深入浅出地介绍了Jav ...
- Java并发编程实战——读后感
未完待续. 阅读帮助 本文运用<如何阅读一本书>的学习方法进行学习. P15 表示对于书的第15页. Java并发编程实战简称为并发书或者该书之类的. 熟能生巧,不断地去理解,就像欣赏一部 ...
- 【Java并发编程实战】----- AQS(二):获取锁、释放锁
上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...
- 【Java并发编程实战】-----“J.U.C”:CyclicBarrier
在上篇博客([Java并发编程实战]-----"J.U.C":Semaphore)中,LZ介绍了Semaphore,下面LZ介绍CyclicBarrier.在JDK API中是这么 ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock
ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/ ...
- 【Java并发编程实战】-----“J.U.C”:Semaphore
信号量Semaphore是一个控制访问多个共享资源的计数器,它本质上是一个"共享锁". Java并发提供了两种加锁模式:共享锁和独占锁.前面LZ介绍的ReentrantLock就是 ...
- 【java并发编程实战】-----线程基本概念
学习Java并发已经有一个多月了,感觉有些东西学习一会儿了就会忘记,做了一些笔记但是不系统,对于Java并发这么大的"系统",需要自己好好总结.整理才能征服它.希望同仁们一起来学习 ...
- java并发编程实战学习(3)--基础构建模块
转自:java并发编程实战 5.3阻塞队列和生产者-消费者模式 BlockingQueue阻塞队列提供可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put ...
- 《java并发编程实战》笔记
<java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为: Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...
随机推荐
- ELK日志应用平台搭建
ELK架构: ElasticSearch:用于存储.索引日志. Logstash:用于收集.处理和转发事件或日志信息的工具. Kibana:搜索和可视化的日志的WEB界面. ELK优点: a.处理方式 ...
- [javascript]模拟汉诺塔
看了博文自己动手写了代码. 这能值几个钱? 请写代码完成汉诺塔的算法:void Hanoi(int maxLevel); 比如2层汉诺塔,需要打印(Console.WriteLine)出如下文本: A ...
- angular测试-Karma + Jasmine配置
首先讲一下大致的流程: 需要node环境,首先先要安装node,node不会?请自行搜索.版本>0.8 安装node完成之后先要测试下npm是否测试通过,如下图所示 首先看下目录结构 目录为:F ...
- 《BI那点儿事》浅析十三种常用的数据挖掘的技术
一.前沿 数据挖掘就是从大量的.不完全的.有噪声的.模糊的.随机的数据中,提取隐含在其中的.人们事先不知道的但又是潜在有用的信息和知识的过程.数据挖掘的任务是从数据集中发现模式,可以发现的模式有很多种 ...
- Spring学习总结(一)——Spring实现IoC的多种方式
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法.没有IoC的程序中我们使用面向对象编程对象的创 ...
- HTML Inspector – 帮助你编写高质量的 HTML 代码
HTML Inspector 是一款代码质量检测工具,帮助你编写更优秀的 HTML 代码.HTML Inspector 使用 JavaScript 编写,运行在浏览器中,是最好的 HTML 代码检测工 ...
- Socket开发框架之框架设计及分析
虽然在APP应用.Web应用.Winform应用等大趋势下,越来越多的企业趋向于这些应用系统开发,但是Socket的应用在某些场合是很必要的,如一些停车场终端设备的接入,农业或者水利.压力监测方面的设 ...
- SignalR入门之基本介绍
SignalR是微软对web开发技术的扩充,它是一种框架,方便用来创建实时应用程序. 有一些即时消息系统,实时协作工作集,多人在线游戏,信息广播服务等其他需要在信息产生时就能进行发送的任务系统. 对于 ...
- 为什么要用 Bootstrap
[Bootstrap](http://hovertree.com/menu/bootstrap/) 是由两个 twitter 员工开发并开源的前端框架,非常火爆,而如此火爆自然有它的道理,在我们团队的 ...
- C#编程总结(十二)断点续传
C#编程总结(十二)断点续传 我们经常使用下载工具,如bit精灵.迅雷.FlashGet,这些软件都支持断点续传. 断点续传即下载任务暂停后可以继续,而无需重新下载,即下载时需要通知服务器的起始位置. ...