对象发布(publish)
含义:一个对象可以在当前作用域之外的代码中使用。
发布方式:如懒汉式、饿汉式、工厂模式等发布的对象。
代码示例:
package com.bicai.publish; import java.util.ArrayList; import java.util.List; /** * @Author lizhengjun * @Date 2020/6/24 * @Desc 发布水果对象(懒汉式) */ public class PublishFruit { private List<String> fruitList = null; /** * @description: 发布水果集合对象(注:线程不安全) * @return: 水果集合对象 * @date: 2020/6/24 15:33 */ public List<String> getInstance() { if(fruitList == null) { // 对象数据初始化 fruitList = new ArrayList<>(); fruitList.add("apple"); fruitList.add("orange"); } return fruitList; } }
测试:
public static void main(String[] args) { PublishFruit publishFruit = new PublishFruit(); // 获取水果集合对象 List<String> fruitList = publishFruit.getInstance(); System.out.println("水果集合对象:" + fruitList); }
输出结果:
水果集合对象:[apple, orange]
对象逸出(escape)
含义:发布对象内部状态可能会破坏封装性,并使得程序难以维持不变性条件;当某个不应该发布的对象被发布时,这种情况就称为逸出。
代码示例:
package com.bicai.publish; /** * @Author lizhengjun * @Date 2020/6/24 * @Desc 对象逸出演示 */ public class EscapeThread { private String taskNumber = "N001"; // 任务编号 private String taskName = null; // 任务名称 public EscapeThread() { new Thread(new EatFruitTask()).start(); new Thread(new EatFruitTask()).start(); // 初始化任务名称 taskName = "吃水果"; } private class EatFruitTask implements Runnable { @Override public void run() { String user = Thread.currentThread().getId() + "---" + Thread.currentThread().getName(); System.out.println(user + ":吃水果...开始"); System.out.println("任务编号taskNumber:" + taskNumber + ",任务名称taskName:" + taskName); System.out.println(user + ":吃水果...结束"); } } }
测试:
public static void main(String[] args) { EscapeThread escapeThread = new EscapeThread(); }
输出结果:
12---Thread-0:吃水果...开始
13---Thread-1:吃水果...开始
任务编号taskNumber:N001,任务名称taskName:null
任务编号taskNumber:N001,任务名称taskName:吃水果
13---Thread-1:吃水果...结束
12---Thread-0:吃水果...结束
对象逸出解决方案
代码示例:
/** * @Author lizhengjun * @Date 2020/6/24 * @Desc 对象逸出解决方案 */ public class EscapeThreadSolution { private String taskNumber = "N001"; // 任务编号 private String taskName = null; // 任务名称 Thread thread1 = null; Thread thread2 = null; public EscapeThreadSolution() { thread1 = new Thread(new EatFruitTask()); thread2 = new Thread(new EatFruitTask()); // 初始化任务名称 taskName = "吃水果"; } public void startTask() { thread1.start(); thread2.start();; } private class EatFruitTask implements Runnable { @Override public void run() { String user = Thread.currentThread().getId() + "---" + Thread.currentThread().getName(); System.out.println(user + ":吃水果...开始"); System.out.println("任务编号taskNumber:" + taskNumber + ",任务名称taskName:" + taskName); System.out.println(user + ":吃水果...结束"); } } }
测试:
public static void main(String[] args) { EscapeThreadSolution escapeThreadSolution = new EscapeThreadSolution(); escapeThreadSolution.startTask(); }
输出结果:
13---Thread-1:吃水果...开始
12---Thread-0:吃水果...开始
任务编号taskNumber:N001,任务名称taskName:吃水果
12---Thread-0:吃水果...结束
任务编号taskNumber:N001,任务名称taskName:吃水果
13---Thread-1:吃水果...结束
解决思路:避免在构造函数里启动线程;
温馨提示
导致对象逸出的情况会有很多,如系统资源初始化、上下文初始化等,针对不同情况采用不同的解决方式。
多线程:对象的发布(publish)、逸出(escape),逸出解决方案
原文:https://www.cnblogs.com/qiancdd/p/13188124.html