java简述对象的组合_【JAVA并发编程实战】2、对象的组合

1、 设计线程安全的类

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

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

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

packagecn.xf.cp.ch04;/***

*功能:JAVA监视器模式的线程安全计数器

*时间:下午6:22:23

*文件:Counter.java

*@authorAdministrator

**/

public classCounter

{//只有这一个变量,这个value就是counter的全部状态

private long value = 0;//获取值,单线程操作

private synchronized longgetValue()

{returnvalue;

}public synchronized longincrement()

{if(value ==Long.MAX_VALUE)throw new IllegalStateException("统计数值溢出");return ++value;

}

}

2、实例封闭

将数据封装在对象内部,可以将数据的访问限制在对象的方法上,从而更容易确保线程在访问数据时总能持有正确的锁。

通过封闭与加锁等机制使一个类成为线程安全的

packagecn.xf.cp.ch04;public classPerson

{privateString name;private intage;private charsex;publicString getName()

{returnname;

}public voidsetName(String name)

{this.name =name;

}public intgetAge()

{returnage;

}public void setAge(intage)

{this.age =age;

}public chargetSex()

{returnsex;

}public void setSex(charsex)

{this.sex =sex;

}

}

packagecn.xf.cp.ch04;importjava.util.HashSet;importjava.util.Set;public classPersonSet

{private final Set mySet = new HashSet();public synchronized voidaddPerson(Person p)

{

mySet.add(p);

}public synchronized booleancontainsPerson(Person p)

{returnmySet.contains(p);

}

}

2、1  Java监视器模式

这个模式的对象会把所有可变状态都封装起来,并由对象自己的内置锁来保护。

packagecn.xf.cp.ch04;/***

*功能:私有锁的使用

*时间:下午9:18:01

*文件:PrivateLock.java

*@authorAdministrator

**/

public classPrivateLock

{//使用私有变量作为对象锁

private final Object myLock = newObject();private inti;public voidsomeMethod()

{synchronized(myLock)

{//这里对状态量i进行操作

i = 110;

System.out.println("私有锁");

}

}

}

私有的锁对象可以将锁封装起来,使客户代码无法获取锁,但是客户代码可以通过公有方法来访问锁,这样也就可以参与到同步中来。

活跃性的问题:死锁, 饥饿和活锁

饥饿(Starvation)

它描述了这样一个场景,当一个线程不能获取定期访问来共享资源而不能继续运行,在共享资源被饥渴线程长期占有时,就会发生饥饿。例如,加速一个对象提供一个要花很长时间才能返回结果的同步方法,如果一个线程频繁调用这个方法,其它线程也需要频繁调用同步进入同一个对象的方法时,阻塞就发生了。

活锁(Livelock)

一个线程经常对另外一个线程的响应做响应的处理,如果线程的另外一个动作同样是对另外一个线程响应而发生,结果可能导致活锁,类似死锁,发生活锁的线程不能更进一步的处理,然而,线程并没有被阻塞,他们只是忙碌于响应对方而重复工作,这类似于两个人在走廊中试图让对方,a移向左以让b通过,而b移向右以让a通过,可以看到,他们仍然互相阻塞,a移动到右边,而b移动到左边,结果他们仍然还是阻塞着。。。

如果不使用私有锁:那么可能客户代码错误地获取另一个对象的锁,可能会产生活跃性的问题(一个并发应用能够及时执行任务的特性称为活跃性)。此外想要验证某个公有访问的锁在程序中是否被正确地使用,则需要检查整个程序,而不是单个类。

2、2 示例:车辆追踪

车辆标识和位置点,类型

packagecn.xf.cp.ch04;public classMutablePoint

{private intx, y;publicMutablePoint()

{

x= 0;

y= 0;

}publicMutablePoint(MutablePoint p)

{this.x =p.getX();this.y =p.getY();

}public synchronized intgetX()

{returnx;

}public synchronized void setX(intx)

{this.x =x;

}public synchronized intgetY()

{returny;

}public synchronized void setY(inty)

{this.y =y;

}

}

车辆追踪类

packagecn.xf.cp.ch04;importjava.util.Collections;importjava.util.HashMap;importjava.util.Map;/***

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

*时间:下午9:50:12

*文件:MonitorVehicleTracker.java

*@authorAdministrator

**/

public classMonitorVehicleTracker

{private final Maplocations;//构造函数对map进行初始化

public MonitorVehicleTracker(Maplocations)

{//为了保持内部数据不会发生逸出,进行深拷贝

this.locations =deepCopy(locations);

}public synchronized MapgetLocations()

{returndeepCopy(locations);

}public synchronizedMutablePoint getLocation(String id)

{//获取要返回的数据

MutablePoint loc =locations.get(id);//创建一个新的对象返回

return loc == null ? null : newMutablePoint(loc);

}public synchronized void setLocation(String id, int x, inty)

{

MutablePoint loc=locations.get(id);if(loc == null)

{//如果没有这个对象的话,抛出异常,还是重新创建,看个人业务

throw new IllegalArgumentException("没有这个id:" +id);

}

loc.setX(x);

loc.setY(y);

}private static Map deepCopy(Mapm)

{//创建一个新的接受数据对象

Map result = new HashMap();//循环取数据

for(String id : m.keySet())

{//根据key取值

result.put(id, m.get(id));

}//返回数据,返回指定映射的不可修改视图。//此方法允许模块为用户提供对内部映射的“只读”访问

returnCollections.unmodifiableMap(result);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值