您的位置:首页 > 编程语言

第三章:并发编程-对象的组合

2018-04-19 23:45 267 查看

本章介绍如何设计线程安全的类


设计线程安全的类

在设计一个线程安全的类的过程中,需要包含以下三个基本要素:

1.找出构成对象状态的所有变量

2.找出约束状态变量的不变性条件

3.建立对象状态的并发访问管理策略。


基于java监视器模式的线程安全计数器

public final class Counter {

private long value = 0;

public synchronized long get(){
return value;
}

public synchronized long increment(){
return ++value;
}
}
通过封闭机制来确保线程安全
public class PersonSet {

private final Set<Person> mySet = new HashSet<>();

public synchronized void addPerson(Person p){
mySet.add(p);
}

public synchronized boolean containPerson(Person p){
return mySet.contains(p);
}

class Person {

}}
实例封闭是构建线程安全的一个最简单方式,它使得在锁策略的选择上拥有了更多的灵活性。

在java平台类库终还有很多线程封闭的实例,其中有些类的唯一用途就是将非线程安全的类转化成线程安全的类,一些基本的容器类并非线程安全的,例如ArrayList和HashMap,但是类库提供了包装器工厂方法,使得这些非线程安全的类可以在多线程环境中安全地使用。这些工厂方法通过装饰器模式,将容器类封装在一个同步的包装器对象中,而包装器对象拥有对底层容器唯一引用,那么它是线程安全的。


基于监视器模式的车辆追踪:

public class MutablePoint {

public int x;
public int y;

public MutablePoint(MutablePoint loc) {
this.x = loc.x;
this.y = loc.y;
}

public MutablePoint(){
this.x = 0;
this.y = 0;
}

}
public class MonitorVehicleTracker {

private final Map<String, MutablePoint> locations;

public MonitorVehicleTracker(Map<String, MutablePoint> locations){
this.locations = deepCopy(locations);
}

private Map<String, MutablePoint> deepCopy(Map<String, MutablePoint> locations) {
Map<String, MutablePoint> result = new HashMap<>();
for(String id : locations.keySet()){
result.put(id, new MutablePoint(locations.get(id)));
}
return Collections.unmodifiableMap(result);
}

public synchronized Map<String, MutablePoint> getLocations(){
return deepCopy(this.locations);
}

public synchronized MutablePoint getLocations(String id){
MutablePoint loc = locations.get(id);
return loc == null ? null : new MutablePoint(loc);
}

public synchronized void setLocations(String id,int x,int y) throws Exception{
MutablePoint loc = locations.get(id);
if(loc == null){
throw new Exception("No such Id : "+id);
}
loc.x = x;
loc.y = y;
}

}
虽然追踪器类是线程安全的,但是车辆容器非常大的情况下将极大地降低性能。

改造成基于委托的车辆追踪器

public class DelegatingVehicleTracker {

private final ConcurrentMap<String, Point> locations;

private final Map<String , Point> unModifiableMap;

public DelegatingVehicleTracker(Map<String , Point> points){
this.locations = new ConcurrentHashMap<String,Point>(points);
this.unModifiableMap = Collections.unmodifiableMap(locations);
}

public Map<String, Point> getLocations(){
return unModifiableMap;
}

public Point getLocation(String id){
return locations.get(id);
}

public void setLocation(String id,int x,int y){
if(locations.replace(id, new Point(x, y)) == null){
throw new IllegalArgumentException("Invalid vehicle name : "+id);
}
}

/**
* 不可变point
* @author c_dingxuehua-001
*
*/
class Point {

public final int x, y;

public Point(int x, int y) {
this.x = x;
this.y = y;
}

}

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: