java 对象 线程安全_Java线程安全性中的对象发布和逸出

发布(Publish)和逸出(Escape)这两个概念倒是第一次听说,不过它在实际当中却十分常见,这和Java并发编程的线程安全性就很大的关系。

什么是发布?简单来说就是提供一个对象的引用给作用域之外的代码。比如return一个对象,或者作为参数传递到其他类的方法中。

什么是逸出?如果一个类还没有构造结束就已经提供给了外部代码一个对象引用即发布了该对象,此时叫做对象逸出,对象的逸出会破坏线程的安全性。

概念我们知道了,可我们要关注什么地方呢?我们要关注的时候就是逸出问题,在不该发布该对象的地方就不要发布该对象,例如以下代码:

1 classUnsafeStates{2 private String[] states = new String[]{"AK", "AL"};3

4 publicString[] getStates(){5 returnstates;6 }7 }

states变量作用域是private而我们在getStates方法中却把它发布了,这样就称为数组states逸出了它所在的作用域。

然而更加隐蔽和需要我们注意的是this逸出,这个问题要引起重点关注。什么是this逸出?观察以下代码:

1 public classThisEscape{2 private intvalue;3 publicThisEscape(EventSource source){4 source.registerListener{5 newEventListener(){6 public voidonEvent(Event e){7 doSomething(e);8 }9 }10 }11 //一些初始化工作

12 value = 7;13 }14

15 public voiddoSomething(Event e){16 System.out.println(value);17 }18

19 }

在构造方法中我们定义了一个匿名内部类,匿名内部类是一个事件监听类,当事件监听类注册完毕后,实际上我们已经将EventListener匿名内部类发布出去了,而此时我们实际上已经携带了this逸出,重点在于这个时候我们还有一些初始化工作没有做完(代码11行之后),这也就是上面所说的,一个类还没有构造结束我们已经将发布了。那怎么来避免this逸出呢?既然我们没有构造完构造函数,那我们就将构造函数构造完嘛,将构造函数定义为private作用域。如以下代码所示:

1 public classSafeListener{2 private finalEventListener listener;3

4 privatesafeListener(){5 listener = newEventListener(){6 public voidonEvent(Event e){7 doSomething(e);8 }9 }10 }11

12 public staticSafeListener newInstance(EventSource source){13 SafeListener safeListener = newSafeListener();14 safeListener.registerListener(safeListener.listener);15

16 returnsafeListener;17 }18 }

我们首先将构造函数设定为private,其次我们在构造函数未完成时不将对象进行发布,而是使用工厂方法,在工厂方法newInstance中待构造函数执行完毕后再将对象进行发布(代码中即为registenerListener注册监听)。这实际上就是修改为了构造完毕->发布对象的串行执行模式,而不是之前的异步模式,这样就不会给我们带来线程安全性的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值