目录
延迟初始化
延迟初始化是一种编程技术,延迟对象的创建,直到第一次被使用。
- 主要优点:节省内存开销。
- 主要缺点:性能不是很好。
一、主程序
package xyz.jangle.thread.test.nxi_8.lazyinit;
/**
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月29日 下午4:46:15
*
*/
public class M {
public static void main(String[] args) {
for (int i = 0; i < 29; i++) {
var task = new Task();
var thread = new Thread(task);
thread.start();
}
}
}
二、正确的预防并发问题方案
package xyz.jangle.thread.test.nxi_8.lazyinit;
/**
* 使用内部静态类的静态final属性,解决高并发时,错误地创建N+个对象。
*
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月29日 下午4:46:46
*
*/
public class DBConnectionOK {
// private static DBConnectionOK dbc;
private DBConnectionOK() {
System.out.println(Thread.currentThread().getName() + ": Connection created.");
}
private static class LazyDBConnection {
private static final DBConnectionOK INSTANCE = new DBConnectionOK();
}
public static DBConnectionOK getConnection() {
return LazyDBConnection.INSTANCE;
// if (dbc == null) {
// dbc = new DBConnectionOK();
// }
// return dbc;
}
}
三、高并发时会出错的延迟初始化方案
使用这种方式,会在高并发时,可能产生不止1个对象,会浪费内存资源
package xyz.jangle.thread.test.nxi_8.lazyinit;
/**
* 使用这种方式,会在高并发时,可能产生不止1个对象,会浪费内存资源
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月29日 下午4:46:46
*
*/
public class DBConnectionERROR {
private DBConnectionERROR() {
System.out.println(Thread.currentThread().getName() + ": Connection created.");
}
private static DBConnectionERROR dbc;
/**
* 使用这种方式,会在高并发时,可能产生不止1个对象,会浪费内存资源
*
* @author jangle
* @time 2020年10月29日 下午5:00:26
* @return
*/
public static DBConnectionERROR getConnection() {
if (dbc == null) {
dbc = new DBConnectionERROR();
}
return dbc;
}
}
四、模拟并发的任务
使用不同的方案,会有不同的直接结果。
package xyz.jangle.thread.test.nxi_8.lazyinit;
/**
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月29日 下午4:51:42
*
*/
public class Task implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ": 获取连接...");
var connection = DBConnectionOK.getConnection();
// var connection = DBConnectionERROR.getConnection();
System.out.println(Thread.currentThread().getName() + ": 连接获取结束..." + connection);
}
}
五、执行结果
正确方案的结果:只有一个 Connection created. 出现。
Thread-0: 获取连接...
Thread-3: 获取连接...
Thread-4: 获取连接...
Thread-2: 获取连接...
Thread-1: 获取连接...
Thread-8: 获取连接...
Thread-7: 获取连接...
Thread-9: 获取连接...
Thread-6: 获取连接...
Thread-5: 获取连接...
Thread-12: 获取连接...
Thread-10: 获取连接...
Thread-13: 获取连接...
Thread-14: 获取连接...
Thread-11: 获取连接...
Thread-15: 获取连接...
Thread-16: 获取连接...
Thread-17: 获取连接...
Thread-18: 获取连接...
Thread-0: Connection created.
Thread-3: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-13: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-14: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-20: 获取连接...
Thread-2: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-18: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-4: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-9: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-16: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-15: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-0: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-10: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-28: 获取连接...
Thread-27: 获取连接...
Thread-17: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-11: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-26: 获取连接...
Thread-25: 获取连接...
Thread-26: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-12: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-5: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-1: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-8: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-6: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-24: 获取连接...
Thread-24: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-7: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-20: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-19: 获取连接...
Thread-23: 获取连接...
Thread-21: 获取连接...
Thread-22: 获取连接...
Thread-21: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-23: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-19: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-25: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-27: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-28: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
Thread-22: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionOK@61e7b029
高并发存在问题的结果:出现了N++ 个Connection created. 说明增加不必要的内存开销。
Thread-1: 获取连接...
Thread-5: 获取连接...
Thread-7: 获取连接...
Thread-6: 获取连接...
Thread-9: 获取连接...
Thread-4: 获取连接...
Thread-2: 获取连接...
Thread-0: 获取连接...
Thread-3: 获取连接...
Thread-11: 获取连接...
Thread-10: 获取连接...
Thread-8: 获取连接...
Thread-13: 获取连接...
Thread-12: 获取连接...
Thread-14: 获取连接...
Thread-0: Connection created.
Thread-11: Connection created.
Thread-0: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@43b3991a
Thread-12: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@49c2adca
Thread-15: 获取连接...
Thread-9: Connection created.
Thread-14: Connection created.
Thread-4: Connection created.
Thread-2: Connection created.
Thread-1: Connection created.
Thread-24: 获取连接...
Thread-3: Connection created.
Thread-25: 获取连接...
Thread-24: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@212c3c52
Thread-1: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@212c3c52
Thread-27: 获取连接...
Thread-2: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@f265828
Thread-23: 获取连接...
Thread-4: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@50ebff79
Thread-22: 获取连接...
Thread-14: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@4bfd1a
Thread-9: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@40cb18f5
Thread-21: 获取连接...
Thread-15: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@49c2adca
Thread-18: 获取连接...
Thread-19: 获取连接...
Thread-20: 获取连接...
Thread-17: 获取连接...
Thread-10: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@49c2adca
Thread-5: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@49c2adca
Thread-7: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@49c2adca
Thread-6: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@49c2adca
Thread-11: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@49c2adca
Thread-16: 获取连接...
Thread-8: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@43b3991a
Thread-13: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@43b3991a
Thread-16: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@7acaf4ee
Thread-17: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@7acaf4ee
Thread-20: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@7acaf4ee
Thread-19: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@7acaf4ee
Thread-18: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@7acaf4ee
Thread-21: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@7acaf4ee
Thread-22: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@7acaf4ee
Thread-23: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@7acaf4ee
Thread-27: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@7acaf4ee
Thread-28: 获取连接...
Thread-26: 获取连接...
Thread-26: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@7acaf4ee
Thread-25: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@7acaf4ee
Thread-3: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@7acaf4ee
Thread-28: 连接获取结束...xyz.jangle.thread.test.nxi_8.lazyinit.DBConnectionERROR@7acaf4ee