发布(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线程安全性中的对象发布和逸出的更多相关文章

  1. Java线程安全性中的对象发布和逸出

    发布(Publish)和逸出(Escape)这两个概念倒是第一次听说,不过它在实际当中却十分常见,这和Java并发编程的线程安全性就很大的关系. 什么是发布?简单来说就是提供一个对象的引用给作用域之外 ...

  2. 【Java并发编程一】线程安全和共享对象

    一.什么是线程安全 当多个线程访问一个类时,如果不用考虑这些线程在运行时环境下的调度和交替执行,并且不需要额外的同步及在调用代码代码不必作其他的协调,这个类的行为仍然是正确的,那么称这个类是线程安全的 ...

  3. java并发编程实战之线程安全性(一)

    1.1什么是线程安全性 要对线程安全性给出一个确切的定义是非常复杂的.最核心的概念就是正确性.正确性:某个类的行为与其规范完全一致.在良好的规范中通常会定义各种不变性条件来约束对象的状态,以及定义各种 ...

  4. Java并发编程实战 之 线程安全性

    1.什么是线程安全性 当多个线程访问某个类时,不管运行时环境采用何种调用方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全 ...

  5. Java并发编程 (五) 线程安全性

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.安全发布对象-发布与逸出 1.发布与逸出定义 发布对象 : 使一个对象能够被当前范围之外的代码所使用 ...

  6. Java并发编程系列-(2) 线程的并发工具类

    2.线程的并发工具类 2.1 Fork-Join JDK 7中引入了fork-join框架,专门来解决计算密集型的任务.可以将一个大任务,拆分成若干个小任务,如下图所示: Fork-Join框架利用了 ...

  7. Java并发编程:Java的四种线程池的使用,以及自定义线程工厂

    目录 引言 四种线程池 newCachedThreadPool:可缓存的线程池 newFixedThreadPool:定长线程池 newSingleThreadExecutor:单线程线程池 newS ...

  8. 【java并发编程实战】-----线程基本概念

    学习Java并发已经有一个多月了,感觉有些东西学习一会儿了就会忘记,做了一些笔记但是不系统,对于Java并发这么大的"系统",需要自己好好总结.整理才能征服它.希望同仁们一起来学习 ...

  9. 【Java并发编程六】线程池

    一.概述 在执行并发任务时,我们可以把任务传递给一个线程池,来替代为每个并发执行的任务都启动一个新的线程,只要池里有空闲的线程,任务就会分配一个线程执行.在线程池的内部,任务被插入一个阻塞队列(Blo ...

随机推荐

  1. Ubuntu 16.04安装KVM

    说明:其实之前我有安装过KVM,只是但是不知道这个就是KVM,而当时只知道叫做QEMU虚拟机. 安装: http://www.cnblogs.com/EasonJim/p/7215836.html h ...

  2. 拍拍CPS入门使用

    1.新建应用,获取应用相应的appOAuthID.appOAuthKey.accessToken(这个一点击获取就会改变的,而且最长有效期为3个月,失效了需要重新获取) http://fuwu.pai ...

  3. ubuntu安装elasticSearch及插件

    原文地址:http://www.niu12.com/article/18 前提 1.安装好Java1.8以上环境并配置好JAVA_HOME(elasticsearch运行环境) 2.node环境6.5 ...

  4. golang错误处理机制:panic与recover

    原文地址:http://www.niu12.com/article/14 panic知识点 package main import ( "fmt" "github.com ...

  5. 基于CSRF的XSS攻击

    有些XSS不好利用啊,比如有些后台的XSS漏洞,你进不了别人的后台,怎么能 利用他的XSS漏洞呢?进得了别人的后台,还利用这个XSS漏洞干什么?其实这个时候可以种个后门(如果那是个持久型的XSS,这是 ...

  6. 一般源码安装添加的GD库 是不支持 jpeg 格式的图片的

    一般源码安装添加的GD库 是不支持 jpeg 格式的图片的,只支持如下格式 GD Support enabled GD Version bundled (2.0.34 compatible) GIF ...

  7. TestNG 二、测试组

    一.测试组 TestNG 允许你将测试方法归类为不同的组.不仅仅是可以声明某个方法属于某个组,而且还可以让组包含其他的组.这样TestNG可以调用或者请求包含一组特定的组 (或者正则表达式)而排除其他 ...

  8. Win7无法安装Flash Player怎么办

    在IE的工具选项中把安全选项中的ActiveX控件一系列都改为启用即可.

  9. vue - static(.gitkeep)

    描述:git上传忽略的文件,与.gitnoignore一样.

  10. [Android] SQLite数据库之增删改查基础操作

        在编程中常常会遇到数据库的操作,而Android系统内置了SQLite,它是一款轻型数据库,遵守事务ACID的关系型数据库管理系统,它占用的资源非常低,可以支持Windows/Linux/Un ...