使用延迟初始化进行预防

Java 9并发编程指南 目录

使用延迟初始化进行预防

延迟初始化是一种常见的编程技术,直到第一次使用对象时才创建。通常会在操作实现中初始化对象,而不是在类构造函数中初始化。这种技术的主要优点是节省内存,因为只创建执行应用所需的必要对象。在一个类中肯能要声明大量对象,但每次程序执行中不会用到所有对象,所以不需要为程序执行中未使用的对象提供内存。这种优势在资源有限的环境中非常有用。

相比之下,因为在操作中需要首次创建对象,所以这种技术的缺点就是应用的性能问题。

在并发应用程序中使用此技术,也会引发问题。由于多个线程能够同时执行一个操作,因此它们可以同时创建一个对象,这种情况可能会有问题。这对于单例类来说具有特殊的重要性。如前所述,应用只有这些类中的一个对象,而并发应用可以创建多个对象。查看如下代码:

public static DBConnection getConnection(){
	if (connection==null) {
		connection=new DBConnection();
	}
	return connection;
}

这是单例类中,使用延迟初始化的典型方法,得到应用中存在类的唯一对象的引用。如果对象尚未创建,则创建对象,最后返回自己。

本节将优雅的实现处理延迟初始化问题的解决方案。

准备工作

本范例通过Eclipse开发工具实现。如果使用诸如NetBeans的开发工具,打开并创建一个新的Java项目。

实现过程

通过如下步骤实现范例:

  1. 创建名为DBConnectionOK的类:

    public class DBConnectionOK {
    
  2. 声明私有构造函数,输出执行的线程名称:

    	private DBConnectionOK() {
    		System.out.printf("%s: Connection created.\n",Thread.currentThread().getName());
    	}
    
  3. 声明名为LazyDBConnectionOK的私有静态类,包含名为INSTANCE的private static final DBConnectionOK实例:

    	private static class LazyDBConnectionOK {
    		private static final DBConnectionOK INSTANCE = new DBConnectionOK();
    	}
    
  4. 实现getConnection()方法,不接收任何参数且返回DBConnectionOK对象,返回INSTANCE对象:

    	public static DBConnectionOK getConnection() {
    		return LazyDBConnectionOK.INSTANCE;
    	}	
    }
    
  5. 创建名为Task的类,指定其实现Runnable接口。实现run()方法,调用DBConnectionOK()方法的getConnection()方法:

    public class Task implements Runnable{
    	@Override
    	public void run() {
    		System.out.printf("%s: Getting the connection...\n", Thread.currentThread().getName());
    		DBConnectionOK connection=DBConnectionOK.getConnection();
    		System.out.printf("%s: End\n", Thread.currentThread().getName());
    	}
    }
    
  6. 实现本范例主类,创建名为Main的类,包含main()方法:

    public class Main {
    	public static void main(String[] args) {
    
  7. 创建20个Task对象和执行它们的20个线程:

    		for (int i=0; i<20; i++){
    			Task task=new Task();
    			Thread thread=new Thread(task);
    			thread.start();
    		}
    	}
    }
    

工作原理

范例的关键是getConnection()方法和private static class LazyDBConnection实例。当第一个线程调用getConnection()方法时,LazyDBConnectionOK类通过调用DBConnectionOK类构造函数初始化INSTANCE对象。对象通过getConnection()方法返回,当剩余线程调用getConnection()方法时,已经创建完对象,因此所有线程使用只创建一次的相同对象。

当运行本范例时,会看到20个任务的起始和结束信息,但只有一条创建信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值