实验四:单例模式 一、实验目的

  1. 掌握单例模式的概念,能够灵活使用单例模式解决相关问题。 二、实验内容 某软件公司开发人员要创建一个数据库连接池,将指定个数的(如3个)数据库连接对象存储在连接池中,客户端代码可以从池中随机取一个连接对象来连接数据库。试通过对单例类进行改造,设计一个能够自行指定个数实例对象的数据库连接类并Java代码编程实现(请分别用饿汉和懒汉单例模式实现)。 要求: 1、画出UML图; 2、给出程序代码,程序代码有恰当的注释。() 3、文档格式正确,排版清晰。 1、UML类图如下: image.png 2.代码如下:
懒汉模式:
ConnectionPool 类:
import java.util.Random;

public class ConnectionPool {
    private Integer connectionInitSize = 3;
    private static volatile ConnectionPool connectionPool;
    private Connection[] connectionList = {null,null,null};

    private ConnectionPool(Integer connectionInitSize) {
        this.connectionInitSize = connectionInitSize;
        for (int i = 0; i < connectionInitSize; i++) {
            Connection connection = new Connection("连接" + i);
            connectionList[i]=connection;
        }
    }

    private static ConnectionPool getInstance() {
        if (connectionPool == null) {
            synchronized (ConnectionPool.class) {
                if (connectionPool == null) {
                    connectionPool = new ConnectionPool(3);
                }
            }
        }
        return connectionPool;
    }

    public static Connection getConnection() {
        Integer nextInt = new Random().nextInt(getInstance().connectionInitSize);
        return getInstance().connectionList[nextInt];
    }
}
Connection 类:
public class Connection {
    private String name;
    public Connection(String name) {
        this.name = name;
    }

    public void doQuery() {
        System.out.println(name + "开始连接");
    }
}
Client 类:
public class Client {
    public static void main(String[] args) {
        Connection connectionA = ConnectionPool.getConnection();
        Connection connectionB = ConnectionPool.getConnection();
        Connection connectionC = ConnectionPool.getConnection();
        connectionA.doQuery();
        connectionB.doQuery();
        connectionC.doQuery();
    }
}

运行结果: image.png

2、程序代码如下:

饿汉单例模式
ConnectionPool 类
import java.util.Random;

public class ConnectionPool {
    private static ConnectionPool connectionPool = new ConnectionPool();
    private static Connection[] connections = {new Connection("连接池1"), new Connection("连接池2"), new Connection("连接池3")};

    public static Connection getConnection() {
        Integer nextInt = new Random().nextInt(3);
        return ConnectionPool.connections[nextInt];
    }
}
Connection 类
public class Connection {
    private String name;
    public Connection(String name) {
        this.name = name;
    }

    public void doQuery() {
        System.out.println(name + "开始连接");
    }
}
Client 类:
public class Client {
    public static void main(String[] args) {
        Connection connectionA = ConnectionPool.getConnection();
        Connection connectionB = ConnectionPool.getConnection();
        Connection connectionC = ConnectionPool.getConnection();
        connectionA.doQuery();
        connectionB.doQuery();
        connectionC.doQuery();
    }
}

运行结果: image.png 3、请叙述饿汉式单例与懒汉式单例的区别。在多线程环境下,懒汉式单例模式如何实现只能创建一个实例对象。 区别: (1)线程安全方面: 饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题, 懒汉式本身是非线程安全的,为了实现线程安全有几种写法。 (2)资源加载和性能方面: 饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成。 而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。 如何实现: 懒汉式单例模式创建对象时使用双重校验锁实现只能创建一个实例对象。