Java并发编程规则设计线程安全的类Word下载.docx
《Java并发编程规则设计线程安全的类Word下载.docx》由会员分享,可在线阅读,更多相关《Java并发编程规则设计线程安全的类Word下载.docx(16页珍藏版)》请在冰豆网上搜索。
*
*@authorBrianGoetzandTimPeierls
*/
@ThreadSafe
publicfinalclassCounter{
@GuardedBy("
this"
)privatelongvalue=0;
publicsynchronizedlonggetValue(){
returnvalue;
}
publicsynchronizedlongincrement(){
if(value==Long.MAX_VALUE)
thrownewIllegalStateException("
counteroverflow"
);
return++value;
}
注:
不理解对象的不可变约束和后验条件,就不能保证线程的安全性。
要约束状态变量的有效值或者状态转换,就需要原子性与封装性。
实例限制:
限制性使构造线程安全的类更容易。
因为类的状态被限制后,分析它的线程安全性时,就不必检查完整的程序。
将数据封装在实体内部,把对数据的访问限制在对象的方法上,更易确保线程在访问数据时总能获得正确的锁。
示例如下:
importjava.util.*;
*PersonSet
*Usingconfinementtoensurethreadsafety
publicclassPersonSet{
)privatefinalSet<
Person>
mySet=newHashSet<
();
publicsynchronizedvoidaddPerson(Personp){
mySet.add(p);
publicsynchronizedbooleancontainsPerson(Personp){
returnmySet.contains(p);
interfacePerson{
HashSet是一个线程安全的类,通过公开的方法进行同步读写操作,确保了线程的安全性。
Java监视器模式:
像Vector和HashTable这样的核心库类,都是采用了Java监视器模式,其最大优势在于简单。
Java监视器模式仅仅是一种习惯约定:
任意锁对象只要始终如一地使用,都可以用来保护对象的状态。
来看个私有锁保护状态的示例:
*PrivateLock
*Guardingstatewithaprivatelock
publicclassPrivateLock{
privatefinalObjectmyLock=newObject();
myLock"
)Widgetwidget;
voidsomeMethod(){
synchronized(myLock){
//Accessormodifythestateofwidget
实际上同步策略中Counter.java也是一个简单的Java监视器模式的示例。
下面是一个基于监视器的机动车追踪器:
*MonitorVehicleTracker
*Monitor-basedvehicletrackerimplementation
publicclassMonitorVehicleTracker{
)privatefinalMap<
String,MutablePoint>
locations;
publicMonitorVehicleTracker(Map<
locations){
this.locations=deepCopy(locations);
publicsynchronizedMap<
getLocations(){
returndeepCopy(locations);
publicsynchronizedMutablePointgetLocation(Stringid){
MutablePointloc=locations.get(id);
returnloc==null?
null:
newMutablePoint(loc);
publicsynchronizedvoidsetLocation(Stringid,intx,inty){
if(loc==null)
thrownewIllegalArgumentException("
NosuchID:
"
+id);
loc.x=x;
loc.y=y;
privatestaticMap<
deepCopy(Map<
m){
Map<
result=newHashMap<
for(Stringid:
m.keySet())
result.put(id,newMutablePoint(m.get(id)));
returnCollections.unmodifiableMap(result);
*MutablePoint
*MutablePointclasssimilartojava.awt.Point
@NotThreadSafe
publicclassMutablePoint{
publicintx,y;
publicMutablePoint(){
x=0;
y=0;
publicMutablePoint(MutablePointp){
this.x=p.x;
this.y=p.y;
委托线程安全:
委托线程安全,就是使用现有的线程安全的类来实现线程安全,即由其代为控制线程安全。
下面来看个使用委托的机动车追踪器,ConcurrentMap线程安全委托:
importjava.util.concurrent.*;
importjava.awt.*;
importjava.awt.Point;
*DelegatingVehicleTracker
*DelegatingthreadsafetytoaConcurrentHashMap
publicclassDelegatingVehicleTracker{
privatefinalConcurrentMap<
String,Point>
privatefinalMap<
unmodifiableMap;
publicDelegatingVehicleTracker(Map<
points){
locations=newConcurrentHashMap<
(points);
unmodifiableMap=Collections.unmodifiableMap(locations);
publicMap<
returnunmodifiableMap;
publicPointgetLocation(Stringid){
returnlocations.get(id);
publicvoidsetLocation(Stringid,intx,inty){
if(locations.replace(id,newPoint(x,y))==null)
invalidvehiclename:
//AlternateversionofgetLocations(Listing4.8)
String,Pnt>
getLocationsAsStatic(){
returnCollections.unmodifiableMap(
newHashMap<
(locations));
*Point
*ImmutablePointclassusedbyDelegatingVehicleTracker
@Immutable
publicclassPoint{
publicfinalintx,y;
publicPoint(intx,inty){
this.x=x;
this.y=y;
Point是不可变对象,它是线程安全的。
来看一下将线程安全委托到多个隐含变量:
importjava.awt.event.KeyListener;
importjava.awt.event.MouseListener;
*VisualComponent
*Delegatingthreadsafetytomultipleunderlyingstatevariables
publicclassVisualComponent{
privatefinalList<
KeyListener>
keyListeners=newCopyOnWriteArrayList<
MouseListener>
mouseListeners=newCopyOnWriteArrayList<
publicvoidaddKeyListener(KeyListenerlistener){
keyListeners.add(listener);
publicvoidaddMouseListener(MouseListenerlistener){
mouseListeners.add(listener);
publicvoidremoveKeyListener(KeyListenerlistener){
keyListeners.remove(listener);
publicvoidremoveMouseListener(MouseListenerlistener){
mouseListeners.remove(listener);
如果一个类由多个彼此独立的线程安全的状态变量组成,并且类的操作不包含任何无效状态转换时,可以将线程安全委托给这些变量。
如果一个状态变量是线程安全的,没有任何不变约束限制它的值,并且没有任何状态转换限制它的操作,那么它可以被安全地发布。
安全发布状态:
底层可变的状态也可以是线程安全的类。
示例:
*SafePoint
publicassSafePoint{
)privateintx,y;
privateSafePoint(int[]a){
this(a[0],a[1]);
publicSafePoint(SafePointp){
this(p.get());
publicSafePoint(intx,inty){
this.set(x,y);
publicsynchronizedint[]get(){
returnnewint[]{x,y};
publicsynchronizedvoidset(intx,inty){
*PublishingVehicleTracker
*Vehicletrackerthatsafelypublishesunderlyingstate
publicclassPublishingVehicleTracker{
String,SafePoint>
publicPublishingVehicleTracker(Map<
this.locations=newConcurrentHashMap<
(locations);
this.unmodifiableMap=Collections.unmodifiableMap(this.locations);
publicSafePointgetLocation(Stringid){
if(!
locations.containsKey(id))
locations.get(id).set(x,y);
扩展已有线程安全类:
重要思想:
缺少即加入。
扩展Vector为例:
*BetterVector
*ExtendingVectortohaveaput-if-absentmethod
publicclassBetterVector<
E>
extendsVector<
{
//Whenextendingaserializableclass,youshouldredefineserialVersionUID
staticfinalgserialVersionUID=-3963416950630760754L;
publicsynchronizedbooleanputIfAbsent(Ex){
booleanabsent=!
contains(x);
if(absent)
add(x);
returnabsent;
使用客户端加锁(缺少即加入):
明确可变约束,加锁的位置很重要。
*ListHelder
*Examplesofthread-safeandnon-thread-safeimplementationsof
*put-if-absenthelpermethodsforList
classBadListHelper<
publicList<
list=Collections.synchronizedList(newArrayList<
());
list.contains(x);