从头认识多线程-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)以及逸出的解决方案。


这一章节就到这里,谢谢

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

我的github:https://github.com/raylee2015/DeepIntoThread


目录:http://blog.csdn.net/raylee2007/article/details/51204573



©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页