当前位置: 代码迷 >> 综合 >> 从头认识多线程-4.1 对象的发布(Publish)、逸出(Escape)以及逸出的解决方案
  详细解决方案

从头认识多线程-4.1 对象的发布(Publish)、逸出(Escape)以及逸出的解决方案

热度:11   发布时间:2023-12-10 03:19:33.0

这一章节我们来讨论一下对象的发布与逸出。

其实在前两个章节我们都有想应的讨论,只不过有一些不用补充的问题,我将会放到这个章节里面去。

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 {@Overridepublic 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 {@Overridepublic 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



  相关解决方案