这一章节我们来讨论一下对象的发布与逸出。
其实在前两个章节我们都有想应的讨论,只不过有一些不用补充的问题,我将会放到这个章节里面去。
1.发布(Publish)
当一个对象能够给其他代码引用。
package com.ray.deepintothread.ch04.topic_1; import java.util.HashMap; public class Publish { private HashMap<String, Object> map = null; public HashMap<String, Object> getMap() { return map; } public void setMap(HashMap<String, Object> map) { this.map = map; } public Publish() { map = new HashMap<String, Object>(); } }
例如上面的map,我们可以通过get方法得到他的引用,这个就叫发布。
如果map是public,我们可以直接通过对象来引用它,如果是public+static,直接可以通过类来引用。
注意:map的发布,代表map里面所有的对象以及发布,也就是说,我可以通过引用map来引用里面所有的对象。
package com.ray.deepintothread.ch04.topic_1; import java.util.HashMap; public class Publish2 { private HashMap<String, Object> map = null; public HashMap<String, Object> getMap() { return map; } public void setMap(HashMap<String, Object> map) { this.map = map; } public Publish2() { map = new HashMap<String, Object>(); map.put("key", "value"); } public void getItemOfMap() { HashMap<String, Object> map = getMap(); Object object = map.get("key"); } }
我们在上面的代码里面增加一个方法,就可以得到相应的引用。
2.逸出(escape)
就是当一个不该发布的对象发不了,就变成了逸出
package com.ray.deepintothread.ch04.topic_1; public class Escape { private int id = 0; private String name = null; public Escape() { new Thread(new MyClass()).start(); new Thread(new MyClass()).start(); name = "ray"; } private class MyClass implements Runnable { @Override public void run() { System.out.println(Escape.this.name); System.out.println(Escape.this.id); } } public static void main(String[] args) { new Escape(); } }
输出:
null
0
ray
0
我们从输出可以看见,其实我们更想看到的结果是两个ray和0,但是其中一个输出跟我们的想象不符,就是因为对象的逸出和多线程的计算造成的。
在引用Escape.this这个对象的时候,其实Escape这个对象还没有构造完成
一般这种现象会出现在在构造函数里面启动线程。
3.逸出的解决方案
package com.ray.deepintothread.ch04.topic_1; public class SolutionOfEscape { private int id = 0; private String name = null; Thread thread1 = null; Thread thread2 = null; public SolutionOfEscape() { thread1 = new Thread(new MyClass()); thread2 = new Thread(new MyClass()); name = "ray"; } public void start() { thread1.start(); thread2.start(); } private class MyClass implements Runnable { @Override public void run() { System.out.println(SolutionOfEscape.this.name); System.out.println(SolutionOfEscape.this.id); } } public static void main(String[] args) { new SolutionOfEscape().start(); } }
输出:
ray
0
ray
0
我们只需要避免在构造函数里面启动线程。
其实我们上面的解决方案只是就上面的一个例子来说的,更深层次的解决方案是,在构造函数执行完之前,要避免使用Object.this这种引用。
总结:这一章节我们讨论了对象的发布(Publish)、逸出(Escape)以及逸出的解决方案。
这一章节就到这里,谢谢
------------------------------------------------------------------------------------
我的github:https://github.com/raylee2015/DeepIntoThread
目录:http://blog.csdn.net/raylee2007/article/details/51204573