Java线程安全性中的对象发布和逸出
发布(Publish)和逸出(Escape)这两个概念倒是第一次听说,不过它在实际当中却十分常见,这和Java并发编程的线程安全性就很大的关系。
什么是发布?简单来说就是提供一个对象的引用给作用域之外的代码。比如return一个对象,或者作为参数传递到其他类的方法中。
什么是逸出?如果一个类还没有构造结束就已经提供给了外部代码一个对象引用即发布了该对象,此时叫做对象逸出,对象的逸出会破坏线程的安全性。
概念我们知道了,可我们要关注什么地方呢?我们要关注的时候就是逸出问题,在不该发布该对象的地方就不要发布该对象,例如以下代码:
class UnsafeStates{
private String[] states = new String[]{"AK", "AL"}; public String[] getStates(){
return states;
}
}
states变量作用域是private而我们在getStates方法中却把它发布了,这样就称为数组states逸出了它所在的作用域。
然而更加隐蔽和需要我们注意的是this逸出,这个问题要引起重点关注。什么是this逸出?观察以下代码:
public class ThisEscape{
private int value;
public ThisEscape(EventSource source){
source.registerListener{
new EventListener(){
public void onEvent(Event e){
doSomething(e);
}
}
}
//一些初始化工作
value = 7;
} public void doSomething(Event e){
System.out.println(value);
} }
在构造方法中我们定义了一个匿名内部类,匿名内部类是一个事件监听类,当事件监听类注册完毕后,实际上我们已经将EventListener匿名内部类发布出去了,而此时我们实际上已经携带了this逸出,重点在于这个时候我们还有一些初始化工作没有做完(代码11行之后),这也就是上面所说的,一个类还没有构造结束我们已经将发布了。那怎么来避免this逸出呢?既然我们没有构造完构造函数,那我们就将构造函数构造完嘛,将构造函数定义为private作用域。如以下代码所示:
public class SafeListener{
private final EventListener listener; private safeListener(){
listener = new EventListener(){
public void onEvent(Event e){
doSomething(e);
}
}
} public static SafeListener newInstance(EventSource source){
SafeListener safeListener = new SafeListener();
safeListener.registerListener(safeListener.listener); return safeListener;
}
}
我们首先将构造函数设定为private,其次我们在构造函数未完成时不将对象进行发布,而是使用工厂方法,在工厂方法newInstance中待构造函数执行完毕后再将对象进行发布(代码中即为registenerListener注册监听)。这实际上就是修改为了构造完毕->发布对象的串行执行模式,而不是之前的异步模式,这样就不会给我们带来线程安全性的问题。
最新文章
- bootstrap
- 深入理解cookies
- Alamofire数据请求
- linux中sudoers别名规则
- [转]Oracle_ProC编程
- Delphi获取当前系统时间(使用API函数GetSystemTime)
- Natural Merge Sort(自然归并排序)
- pfSense配置基于时间的防火墙规则
- MyEclipse 新手使用教程---图文详解
- mysql安装运行(centos)
- HBase数据模型
- DosBox 的 DOSBOX.CONF 的详细配置说
- git log 的常用选项
- push问题1
- 混合pyqt和qtcreator (2): Impl a image viewer (can show FIji ROI manager data)
- U3D学习005——输入操作
- VIM初掌握
- 20145329 吉东云《Java程序设计》第二周学习总结
- JVM Object Query Language (OQL) 查询语言
- 【转】Sublime Text2中的快捷键一览表(Sublime 键盘快捷键大全 )
热门文章
- MongoDB基础教程系列--第三篇 MongoDB基本操作(二)
- 【Egret】3D 使用中的一些疑难解决技巧!
- Debian 8开启sftp服务
- Hibernate(二)之Hibernate-api详解
- [转载]转载一篇好文章作为Java与面向对象之随感(3)
- ecshop打开手机端QQ对话窗口
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(九)数据层优化-jdbc连接池简述、druid简介
- js中字符串转换为日期型
- jmeter执行case结果插入DB数据优化
- 商城项目实战 | 1.1 Android 仿京东商城底部布局的选择效果 —— Selector 选择器的实现