JAVA concurrency学习笔记之发布与溢出

JAVA concurrency学习笔记之"发布" 与 "溢出"

-------------------------------------------------------------------------------------------------------------------------------------------

今晚闲来无事决定看看拿去了很久没看的java并发编程,刚好看到了一个自己不知道的东西,于是兴致所致,决定写一篇博客记录下

进入正题: 什么是发布(Publish)呢?在java并发编程实战这本书里面是这样定义的:"发布"一个对象的意思是指,使对象能够在当前作用域以外的代码中使用。

书中还具体说了三种发布行为:

  1.  将一个指向该对象的引用保存到其他代码可以访问的地方
  2.  在某一个非私有的方法中返回该引用
  3.  将引用传递到其他类的方法中
  4. 发布一个内部的类实例(这种稍微复杂点)

下面我们一起来看一下这几种情况都是怎么溢出的,并且产生线程问题

首先来看下第一种 

package com.example.demo.publishAndEscape;

import java.util.HashSet;
import java.util.Set;

public class PublishObject {
    public static Set<String> numbers;

    public void initialize() {
        numbers = new HashSet<>();
        System.out.println("numbers object hashcode is " + numbers.getClass().hashCode());
    }
}

 测试代码

package com.example.demo;


import com.example.demo.publishAndEscape.PublishObject;

public class DemoApplication {

    public static void main(String[] args) {
        PublishObject object = new PublishObject();
        for (int i = 0; i < 50; i++) {
            Thread t1= new Thread(() -> {
                object.initialize();
                System.out.println("object hashcode is " + PublishObject.numbers.getClass().hashCode());
                PublishObject.numbers.add("aaaa");
            });
            Thread t2= new Thread(() -> {
                System.out.println(PublishObject.numbers.contains("aaaa"));
            });
            t1.start();
            t2.start();
        }
    }

}

结果

果然 溢出的对象始终是那一个,有可能这个例子不是很好,大家包容吧

接下来我们看看非私有方法返回的问题

package com.example.demo.publishAndEscape;

public class UnsafeStates {
    private String[] sates = new String[] {"AK","AL","AE"};

    public String[] getSates() {
        System.out.println(Thread.currentThread().getName()+":innner,state item object hashcode is" + sates[1].hashCode() + sates[1]);
        return sates;
    }
}

测试一:

package com.example.demo;


import com.example.demo.publishAndEscape.UnsafeStates;

public class DemoApplication {

    public static void main(String[] args) {

            Object obj = new Object();
            Thread t1= new Thread(() -> {
                    UnsafeStates states = new UnsafeStates();
                    System.out.println("change after,state item object hashcode is" + states.getSates()[1].hashCode() +
                            states.getSates()[1]);
            });
            Thread t2= new Thread(() -> {
                    UnsafeStates states = new UnsafeStates();
                    System.out.println("change after,state item object hashcode is" + states.getSates()[1].hashCode() +
                            states.getSates()[1]);
            });
            t1.start();
            t2.start();
        }

}

结果:

结果发现不管是在类的内部还是外部我们始终操作的是一个类,现在我们把测试代码该一下就能发现线程问题了

package com.example.demo;


import com.example.demo.publishAndEscape.UnsafeStates;

public class DemoApplication {

    public static void main(String[] args) {

            Object obj = new Object();
            Thread t1= new Thread(() -> {
                    UnsafeStates states = new UnsafeStates();
                    states.getSates()[1]="a";
                    System.out.println("change after,state item object hashcode is" + states.getSates()[1].hashCode() +
                            states.getSates()[1]);
            });
            Thread t2= new Thread(() -> {
                    UnsafeStates states = new UnsafeStates();
                    System.out.println("change after,state item object hashcode is" + states.getSates()[1].hashCode() +
                            states.getSates()[1]);
            });
            t1.start();
            t2.start();
        }

}

最后在看一种内部类的实例,这个比较隐式,不容易看出来

 

package com.example.demo.publishAndEscape;

public class ThisEscape {
    public ThisEscape(EventSource source) {
        source.registListener(new EventListener() {
            @Override
            public void onEvent(Event e) {
                System.out.println("event publish "+e.getName());
            }
        });
    }
}

测试类

package com.example.demo;


import com.example.demo.publishAndEscape.Event;
import com.example.demo.publishAndEscape.EventListener;
import com.example.demo.publishAndEscape.EventSource;
import com.example.demo.publishAndEscape.ThisEscape;

public class DemoApplication {

    public static void main(String[] args) {
        EventSource eventSource = new EventSource() {
            @Override
            public void registListener(EventListener listener) {
                listener.onEvent(new Event("sleep"));
            }
        };
        ThisEscape escape = new ThisEscape(eventSource);
    }

}

结果

从结果我们可以看出,虽然只是注册了个listener,却隐式的也把ThisEscape个发布出去了,溢出了

 

这便是发布与溢出,个人学习理解,学习理解能力有限,如有错误欢迎大佬指出,我们一起进步 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值