从头认识多线程-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

时间: 2024-10-14 20:45:18

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

Java 并发编程(二)对象的发布逸出和线程封闭

对象的发布与逸出 "发布(Publish)"一个对象是指使对象能够在当前作用域之外的代码中使用.可以通过 公有静态变量,非私有方法,构造方法内隐含引用 三种方式. 如果对象构造完成之前就发布该对象,就会破坏线程安全性.当某个不应该发布的对象被发布时,这种情况就被称为逸出(Escape). 下面我们首先来看看一个对象是如何逸出的. 发布对象最简单的方法便是将对象的引用保存到一个共有的静态变量中,以便任何类和线程都能看见对象,如下面代码. public static Set<Stri

对象的发布与逸出

介绍发布与逸出的定义及代码示范,以及如何使用工厂方法避免this引用在构造方法中逸出 发布: “发布”一个对象是指,使对象能够在当前作用域之外的代码中使用. 例如:将一个指向该对象的引用保存到其他代码可以访问的地方,或者在某一个非私有的方法中返回该对象的引用,或者将引用传递到其他类的方法中. 代码示范:将一个指向该对象的引用,保存到其他代码可以访问的地方. // 保存在一个共有的静态变量中 public static Set<Secret> knowSecrets; public void i

从头认识多线程-2.8 缓解同步方法的隐患-同步代码块

这一章节我们来讨论一下缓解同步方法的隐患-同步代码块. 1.思路:把同步方法,降低同步的粒度,同步到代码块 2.根据上一章节的例子,我们把代码修改一下 (1)第一种方法,把同步标记移到更新的那一栏里面去,一般来说大部分都是更新的时候需要同步数据 package com.ray.deepintothread.ch02.topic_9; /** * 从头认识多线程-2.8 缓解同步方法的隐患-同步代码块<br> * * @author RayLee * */ public class Relief

SQLServer 事务复制中使用脚本添加某个对象的发布

原文:SQLServer 事务复制中使用脚本添加某个对象的发布 -- use [发布库] --添加表:创建项目并将其添加到发布中 exec sp_addarticle @publication = N'ReplicationName', @article = N'MyObject', @source_owner = N'dbo', @source_object = N'MyObject', @destination_owner = N'dbo', @destination_table = N'M

多线程对同一个对象操作

多线程实现的两种方式: 继承Thread类 实现Runnable接口 这两种方式都必须重写run()方法. 当多线程对同一个对象操作时,必须实现Runnable接口,而不能继承Thread类.因为继承Thread类实现多线程时,操作的是不同的对象. 1 Runnable r=new RunnableImpl(); 2 Thread t1=new Thread(r); 3 Thread t2=new Thread(r); 4 t1.start(); 5 t2.start(); 两个线程传同一个对象

JavaScript学习总结(一)——延迟对象、跨域、模板引擎、弹出层、AJAX示例

JavaScript学习总结(一)--延迟对象.跨域.模板引擎.弹出层.AJAX示例 目录 一.AJAX示例 1.1.优点 1.2.缺点 1.3.jQuery AJAX示例 二.延迟对象(Deferred) 2.1.回调函数 2.2.deferred.done 三.跨域 3.1.什么是跨域 3.2.JSONP跨域 3.3.jQuery使用JSONP跨域 3.4.跨域资源共享(CORS) 3.5.小结 四.弹出层 五.模板引擎 5.1.Hello World 5.2.方法 5.3.与AJAX结合应

发布逸出 java this 逸出【转】

转自:http://blog.csdn.net/joker_zhou/article/details/7322801 (1)发布:发布是指将一个对象,使其引用储存到一个其他代码可以访问到的地方,在一个非私有方法返回这个引用,也可以把它传递到其他对象中. a)  发布最简单的就是将对象设置到公共静态域中 b)  发布第二种简单的方式就是在一个公共方法内直接return 对象的引用 第三种的发布就很隐秘了.就是讲自身的对象引用发布到另一个对象的引用中.可能在构造中出现如此这就是this例如:这样 s

发布或重启线上服务时抖动问题解决方案

发布或重启线上服务时抖动问题解决方案 一.问题描述       在发布或重启某线上某服务时(jetty8作为服务器),常常发现有些机器的load会飙到非常高(高达70),并持续较长一段时间(5分钟)后回落(图1),与此同时响应时间曲线(图2)也与load曲线一致.注:load飙高的初始时刻是应用服务端口打开,流量打入时(load具体指什么可参考http://www.cnblogs.com/amsun/p/3155246.html). 图1 发布时候load飙高 图2 发布时候响应时间飙高 二.问

Unity 3D本地发布WebPlayer版时&quot;Failed to download data file&quot;解决方案

Unity 3D本地发布WebPlayer版时遇到提示:"Failed to download data file"(如上图),遇到这个问题就是指Web服务器并没有支持这种*.unity3d文件类型.需要做的是在Web服务器中添加MIME类型: 1.IIS 7 及以上版本: 在功能视图的IIS选项卡中: 双击打开MIME,选择"添加": .unity3d application/octet-stream 2.IIS6版本: 右击计算机名,选择属性,找到MIME类型,