Java并发编程(五):Java线程安全性中的对象发布和逸出
发布(Publish)和逸出(Escape)这两个概念倒是第一次听说,不过它在实际当中却十分常见,这和Java并发编程的线程安全性就很大的关系。
什么是发布?简单来说就是提供一个对象的引用给作用域之外的代码。比如return一个对象,或者作为参数传递到其他类的方法中。
什么是逸出?如果一个类还没有构造结束就已经提供给了外部代码一个对象引用即发布了该对象,此时叫做对象逸出,对象的逸出会破坏线程的安全性。
概念我们知道了,可我们要关注什么地方呢?我们要关注的时候就是逸出问题,在不该发布该对象的地方就不要发布该对象,例如以下代码:
1 class UnsafeStates{ 2 private String[] states = new String[]{"AK", "AL"}; 3 4 public String[] getStates(){ 5 return states; 6 } 7 }
states变量作用域是private而我们在getStates方法中却把它发布了,这样就称为数组states逸出了它所在的作用域。
然而更加隐蔽和需要我们注意的是this逸出,这个问题要引起重点关注。什么是this逸出?观察以下代码:
1 public class ThisEscape{2 private int value;3 public ThisEscape(EventSource source){4 source.registerListener{5 new EventListener(){6 public void onEvent(Event e){7 doSomething(e);8 }9 } 10 } 11 //一些初始化工作 12 value = 7; 13 } 14 15 public void doSomething(Event e){ 16 System.out.println(value); 17 } 18 19 }
在构造方法中我们定义了一个匿名内部类,匿名内部类是一个事件监听类,当事件监听类注册完毕后,实际上我们已经将EventListener匿名内部类发布出去了,而此时我们实际上已经携带了this逸出,重点在于这个时候我们还有一些初始化工作没有做完(代码11行之后),这也就是上面所说的,一个类还没有构造结束我们已经将发布了。那怎么来避免this逸出呢?既然我们没有构造完构造函数,那我们就将构造函数构造完嘛,将构造函数定义为private作用域。如以下代码所示:
1 public class SafeListener{2 private final EventListener listener;3 4 private safeListener(){5 listener = new EventListener(){6 public void onEvent(Event e){7 doSomething(e);8 }9 } 10 } 11 12 public static SafeListener newInstance(EventSource source){ 13 SafeListener safeListener = new SafeListener(); 14 safeListener.registerListener(safeListener.listener); 15 16 return safeListener; 17 } 18 }
我们首先将构造函数设定为private,其次我们在构造函数未完成时不将对象进行发布,而是使用工厂方法,在工厂方法newInstance中待构造函数执行完毕后再将对象进行发布(代码中即为registenerListener注册监听)。这实际上就是修改为了构造完毕->发布对象的串行执行模式,而不是之前的异步模式,这样就不会给我们带来线程安全性的问题。
Java并发编程(五):Java线程安全性中的对象发布和逸出相关推荐
- java并发编程实践(2)线程安全性
[0]README 0.0)本文部分文字描述转自:"java并发编程实战", 旨在学习"java并发编程实践(2)线程安全性" 的相关知识: 0.1)几个术语( ...
- Java并发(五)线程池使用番外-分析RejectedExecutionException异常
Java并发(五)线程池使用番外-分析RejectedExecutionException异常 参考文章: (1)Java并发(五)线程池使用番外-分析RejectedExecutionExcepti ...
- 视频教程-Java并发编程实战-Java
Java并发编程实战 2018年以超过十倍的年业绩增长速度,从中高端IT技术在线教育行业中脱颖而出,成为在线教育领域一匹令人瞩目的黑马.咕泡学院以教学培养.职业规划为核心,旨在帮助学员提升技术技能,加 ...
- 【Java并发编程】Java多线程(四):FutureTask 源码分析
前言:[Java并发编程]Java多线程(三):Runnable.Callable --创建任务的方式 在上一篇文章的末尾我们通过两个问题,引出了 FutureTask 及其设计思路,先来回顾一下: ...
- Java并发编程—什么是线程?
原文作者:way_more 原文地址:Java 多线程常见基础面试题总结,面试必看! 目录 一.什么是线程和进程? 二.简要描述线程与进程的关系 三.FAQ 一.什么是线程和进程? 1.1. 何为进程 ...
- java并发编程第一课 线程的创建、停止和状态变更
开篇词: 由点及面,搭建你的 Java 并发知识网 你好,欢迎学习<Java 并发编程核心 78 讲>,我是讲师星星,一线互联网公司资深研发工程师,参与过集团内多个重点项目的设计与开发. ...
- java并发编程实践学习---java的类锁和对象锁
最近在看Java Concurrent in Practice(java并发编程实践),发现自己对java的线程.锁等机制,理解很肤浅,学习的也不够全面.打算借着这本书,全面的学习下JDK的并发包和一 ...
- Java并发编程(02):线程核心机制,基础概念扩展
本文源码:GitHub·点这里 || GitEE·点这里 一.线程基本机制 1.概念描述 并发编程的特点是:可以将程序划分为多个分离且独立运行的任务,通过线程来驱动这些独立的任务执行,从而提升整体的效 ...
- Java并发编程(01):线程的创建方式,状态周期管理
本文源码:GitHub·点这里 || GitEE·点这里 一.并发编程简介 1.基础概念 程序 与计算机系统操作有关的计算机程序.规程.规则,以及可能有的文件.文档及数据. 进程 进程是计算机中的程序 ...
最新文章
- HTML输入 - 名称与ID
- 简述WebService与.NET Remoting的区别及适应场合
- C++:44---关键字virtual、override、final
- JAVA知识基础(四):深入理解static关键字
- 【转】HTML5杂谈 概念与现行游戏 割绳子 宝石迷阵
- robotframework 测试工具添加PDF文件内容匹配插件
- VMC to Hyper-V Import Tool 简体中文版.VZPEDIA首发
- 支付宝新漏洞引发恐慌,那如何关闭小额免密支付呢
- plc vb c语言编程,[转载]VB6.0在PLC和上位机通讯中的应用【工控老鬼分享】
- 求帮忙,给python中安装matplotlib系统里有但是显示不出来,万分感谢啊大家
- 腾讯云TVP专家眼中的云开发:尚不完美,未来可期
- 随手口袋记APP支持
- 前端插件日常问题 整理
- Lorem ipsum乱数假文学习笔记
- 博客地址blog.geass.link
- IDEA 配置连接数据库报错 Server returns invalid timezone. Need to set ‘serverTimezone‘ property.
- 正态分布(normal distribution)与偏态分布(skewed distribution)
- Tomcat 中文文档(一)
- Java判断一个数组是否有相同的元素
- 万维考试系统python_万维考试系统客户端下载|万维自动考试系统下载 v1.0 官方版_最火软件站...
热门文章
- 抖音上测试年龄星座的软件,抖音年龄计算器
- C++11 unique_ptr用法
- 计算机维修工中级实践考试,计算机维修工(中级)技能考核.doc
- mysql 百度地图插件_GitHub - huizhong/grafana-baidumap-panel: Grafana 百度地图插件
- centos 编译nginx php mariadb,centos7安装nginx+mariadb+php-fpm
- Bug in Code CodeForces - 420C (计数,图论)
- runtime-归档
- 【Zookeeper】编程实战之Zookeeper分布式锁实现秒杀
- Mongodb的锁 原子性 隔离性 一致性
- 0069 如何在Intellij IDEA中查看Spring MVC项目的所有请求与处理方法的映射列表