#从头认识多线程-4.1 对象的发布(Publish)、逸出(Escape)以及逸出的解决方案/n
从头认识多线程-4.1 对象的发布(Publish)、逸出(Escape)以及逸出的解决方案
这一章节我们来讨论一下对象的发布与逸出。
其实在前两个章节我们都有想应的讨论,只不过有一些不用补充的问题,我将会放到这个章节里面去。
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)以及逸出的解决方案。
这一章节就到这里,谢谢
------------------------------------------------------------------------------------
╰(*°▽°*)╯ (dadaguo-dadaguo)