【java】知识系谱-基础篇-线程-发布、逸出

java并发编程实战的解释,不够详细,尤为this引用逸出让人理解有些费解,java并发编程实战里面的内容就直接拷贝过来java

发布:使对象可以在当前做用域以外的代码中使用
逸出:当某个不应被发布的对象被发布时,这种状况称为逸出
发布内部状态将会破坏封装性,并使得程序难以维持不变性条件
当某个对象逸出后,必须对程序进行分析,以便找出哪些对象或线程可能会误用该对象,这正是使用封装的最主要缘由:使对程序的正确性分析变为可能,并使无心中破坏设计约束条件变得更难
不管其它的线程会对逸出的对象引用执行何种操做,都不重要,由于误用该引用的风险始终是客观存在的

发布的实现方式

1.对象引用做为非私有属性

代码示例:编程

//只是代码示例,不推荐这样初始化List
public class test {
    public List<Animal> animals = new ArrayList<Animal>(){{
        add(new Animal());
    }};
}

List对象和List中的Animal对象都被发布出去。并发

2.对象引用被非私有方法返回

代码示例:函数

//只是代码示例,不推荐这样初始化List
public class test {
    private List<Animal> animals = new ArrayList<Animal>(){{
        add(new Animal());
    }};
    
    public List<Animal> getAnimals(){
        return animals;
    }
}

一、2的同样,List对象和List中的Animal对象发布出去。只是一个是方法发布出去,一个是属性发布出去。this

3.外部方法发布对象

外部方法定义:
对当前类来讲,外部方法是指行为不彻底由当前类来规定的方法,包括其余类中定义的方法以及当前类中能够被改写的方法(既不是私有方法,也不是final方法)

代码示例:线程

public class test {
    public void setAnimals(Animal animal){
        animal.setDag(
            new Dog(){
                public void doSomething(){
                     ...
                };
            }
        )
    }
}

当前类test来讲,setDag为外部方法,Dog就被发布了。设计

this引用逸出

基于外部方法发布对象引出this引用逸出问题。直接拿java并发编程实战的代码code

public class ThisEscape {
    public ThisEscape(EventSource source){
        source.registerListener(
            new EventListener(){
                public void onEvent(Event e){
                    doSomething(e)
                }
            });
    }
}
java并发编程实战的解释:
当ThisEscape发布EventListener时,它也无条件地发布了封装(enclosing)ThisEscape的实例,由于内引类(inner class inst ances)的实例包含了对封装实例隐含的引用。

这里发布new EventListener()内部对象,隐式的有个this。也就是ThisEscape也会被发布出去,可是ThisEscape尚未构建完成,存在逸出的可能,ThisEscape在未构建完成被发布了。怎么处理这个可能逸出的问题,就是让ThisEscape构建完成再发布出去就能够了。java并发编程实战的提到私有构造函数+公共的工厂方法解决可能逸出的问题。对象

public class ThisEscape {
    private final EventListener listener;
    
    private ThisEscape(){
        listener = new EventListener(){
            public void onEvent(Event e){
                doSomething(e)
            }
        };
    }
    
    public static ThisEscape newInstance(EventSource source){
        ThisEscape thisEscape = new ThisEscape();
        source.registerListener(thisEscape.listener);
        return thisEscape;
    }
    
}

同理在构造函数能够新建线程,当不要start()。start()的话this被新线程共享。下面代码就是错误的:作用域

public class ThisEscape {  
    private Thread thread;  
    public ThisEscape(){    
        thread = new Thread(){  
            public void run(){  
                   ...
            }  
        };  
        thread.start(); //能够在构造函数中new Thread 可是不要start
    }  
      
    public static void main(String[] args){  
        ThisEscape a = new ThisEscape();  
    }  
}
相关文章
相关标签/搜索