- 问题一:什么是this逃逸
this逃逸是指构造函数返回之前其他线程持有该对象的引用,this逃逸经常发生在构造函数中启动线程或注册监听器。
public class ThisEscape {
private String value = "";
public ThisEscape() {
new Thread(new TestDemo()).start();
this.value = "this escape";
}
public class TestDemo implements Runnable {
@Override
public void run() {
/**
* 这里是可以通过ThisEscape.this调用外围类对象的,但是测试外围累对象可能还没有构造完成,
* 所以会发生this逃逸现象
*/
System.out.println(ThisEscape.this.value);
}
}
}
正确方式应该如下:
public class FixThisEscape {
private String value = "";
private Thread thd;
public FixThisEscape() {
/**
* 构造函数中可以创建Thread对象,但是不要启动,另外使用start方法启动线程
*/
thd = new Thread(new TestDemo());
this.value = "this escape";
}
public void start() {
thd.start();
}
public class TestDemo implements Runnable {
@Override
public void run() {
System.out.println(FixThisEscape.this.value);
}
}
}
- 问题二:为什么要用线程池?
在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其他更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁。如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些“池化资源”技术产生的原因。比如大家熟知的数据库连接池正是遵循这一思想产生。