this引用逃逸问题

2019-08-15  本文已影响0人  slowwalkerlcr
  1. 实例一:t2打印出来的a为null
/**
 * 解决this逃逸的最好方法就是不要在构造方法中将this传递出去
 * 
 */
public class ThisEscapeOne {
    final String a;
    static ThisEscapeOne t;
    //这里将语句1写在最后也无效,因为可能会发生重排序,仍会发生逃逸
    public ThisEscapeOne() {
        t = this;       //1
        //这里延时200ms,模拟构造方法其他字段的初始化
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        a = "ABC";      //2
    }
    public static void main(String[] args) {
        //t1进行构造对象
        Thread t1 = new Thread(() -> {
            new ThisEscapeOne();
        });
        //t2观测常量的值
        Thread t2 = new Thread(() -> {
            System.out.println(ThisEscapeOne.t.a);
        });
        t1.start();
        //尽量保证t1先启动
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
        }
        t2.start();
    }
}

2.示例二,打印结果为:Source:ThisEscapeTwo [id=null]

/**
 * 对于相互包含的类,通过构造函数将自己set时可能会发生this逃逸
 */
public class ThisEscapeTwo {
    protected final String id;
    public ThisEscapeTwo(DataSource source) {
        source.setThisEscapeTwo(this);
        //延时100ms,可能是初始化其它字段,也可能是其他耗时的操作
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
        }
        id = "ABC";
    }
    public void getMessage(String mess) {
        System.out.println("Source:" + mess);
    }
    @Override
    public String toString() {
        return "ThisEscapeTwo [id=" + id + "]";
    }
    public static void main(String[] args) {
        final DataSource s = new DataSource();
        Thread t = new Thread(() -> {
            new ThisEscapeTwo(s);
        });
        t.start();
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        s.postMessage();
    }
}
//数据源
class DataSource {
    private ThisEscapeTwo escapeTwo;
    public void setThisEscapeTwo(ThisEscapeTwo escapeTwo) {
        this.escapeTwo = escapeTwo;
    }
    public void postMessage() {
        if (this.escapeTwo != null) {
            escapeTwo.getMessage(escapeTwo.toString());
        }
    }
}

上一篇 下一篇

猜你喜欢

热点阅读