如何写一个标准的Java单例模式

发布网友 发布时间:2022-04-24 01:44

我来回答

2个回答

懂视网 时间:2022-05-01 02:41

  •         ds.setInitialPoolSize(3);  

  •         //连接池中保留的最大连接数。Default:  15 maxPoolSize  

  •         ds.setMaxPoolSize(100);  

  •           

  •         //// 连接池中保留的最小连接数。  

  •         //ds.setMinPoolSize(1);  

  •           

  •         //当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 acquireIncrement    

  •         ds.setAcquireIncrement(10);  

  •   

  •         //每60秒检查所有连接池中的空闲连接。Default: 0  idleConnectionTestPeriod  

  •         ds.setIdleConnectionTestPeriod(60);  

  •          

  •         //最大空闲时间,25000秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0  maxIdleTime  

  •         ds.setMaxIdleTime(25000);  

  •         //连接关闭时默认将所有未提交的操作回滚。Default: false autoCommitOnClose  

  •         ds.setAutoCommitOnClose(true);  

  •   

  •         //定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:  

  •         //测试的表必须在初始数据源的时候就存在。Default: null  preferredTestQuery  

  •         ds.setPreferredTestQuery("select sysdate from dual");  

  •         // 因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的  

  •         // 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable  

  •         // 等方法来提升连接测试的性能。Default: false testConnectionOnCheckout  

  •         ds.setTestConnectionOnCheckout(true);  

  •         //如果设为true那么在取得连接的同时将校验连接的有效性。Default: false  testConnectionOnCheckin  

  •         ds.setTestConnectionOnCheckin(true);  

  •   

  •         //定义在从数据库获取新连接失败后重复尝试的次数。Default: 30  acquireRetryAttempts  

  •         ds.setAcquireRetryAttempts(30);  

  •         //两次连接中间隔时间,单位毫秒。Default: 1000 acquireRetryDelay  

  •         ds.setAcquireRetryDelay(1000);  

  •         //获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效  

  •         //保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试  

  •         //获取连接失败后该数据源将申明已断开并永久关闭。Default: false  breakAfterAcquireFailure  

  •         ds.setBreakAfterAcquireFailure(true);  

  •          

  •          

  •   

  •         //        <!--当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出  

  •         //        SQLException,如设为0则无限期等待。单位毫秒。Default: 0 -->  

  •         //        <property name="checkoutTimeout">100</property>  

  •   

  •         //        <!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么  

  •         //        属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试  

  •         //        使用。Default: null-->  

  •         //        <property name="automaticTestTable">Test</property>  

  •   

  •         //        <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements  

  •         //        属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。  

  •         //        如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->  

  •         //        <property name="maxStatements">100</property>  

  •   

  •         //        <!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->  

  •         //        <property name="maxStatementsPerConnection"></property>  

  •   

  •         //        <!--c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能  

  •         //        通过多线程实现多个操作同时被执行。Default: 3-->  

  •         //        <property name="numHelperThreads">3</property>  

  •   

  •         //        <!--用户修改系统配置参数执行前最多等待300秒。Default: 300 -->  

  •         //        <property name="propertyCycle">300</property>  

  •   

  •     }  

  •   

  •     public  static  final ConnectionManager getInstance() {  

  •         if (instance == null) {  

  •             try {  

  •                 instance = new ConnectionManager();  

  •             } catch (Exception e) {  

  •                 e.printStackTrace();  

  •             }  

  •         }  

  •         return instance;  

  •     }  

  •   

  •     public synchronized   final Connection getConnection() {  

  •         try {  

  •             return ds.getConnection();  

  •         } catch (SQLException e) {  

  •             e.printStackTrace();  

  •         }  

  •         return null;  

  •     }  

  •   

  •     protected void finalize() throws Throwable {  

  •         DataSources.destroy(ds); //关闭datasource  

  •         super.finalize();  

  •     }  

  •   

  • 经典的单例模式c3p0来控制数据库连接池

    标签:

    热心网友 时间:2022-04-30 23:49

    java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。
    单例模式有一下特点:
    1、单例类只能有一个实例。
    2、单例类必须自己自己创建自己的唯一实例。
    3、单例类必须给所有其他对象提供这一实例。
    单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。
    首先看一个经典的单例实现。
    public class Singleton {
    private static Singleton uniqueInstance = null;

    private Singleton() {
    // Exists only to defeat instantiation.
    }

    public static Singleton getInstance() {
    if (uniqueInstance == null) {
    uniqueInstance = new Singleton();
    }
    return uniqueInstance;
    }
    // Other methods...
    }
    Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)
    但是以上实现没有考虑线程安全问题。所谓线程安全是指:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。显然以上实现并不满足线程安全的要求,在并发环境下很可能出现多个Singleton实例。

    //////////////////////////////////////////////////////////////////////
    验证单例模式的示例
    //////////////////////////////////////////////////////////////////////
    public class TestStream {
    private String name;
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    // 该类只能有一个实例
    private TestStream() {
    } // 私有无参构造方法
    // 该类必须自行创建
    // 有2种方式

    private static TestStream ts1 = null;
    // 这个类必须自动向整个系统提供这个实例对象
    public static TestStream getTest() {
    if (ts1 == null) {
    ts1 = new TestStream();
    }
    return ts1;
    }
    public void getInfo() {
    System.out.println("output message " + name);
    }
    public static void main(String[] args) {
    TestStream s = TestStream.getTest();
    s.setName("张孝祥 1");
    System.out.println(s.getName());
    TestStream s1 = TestStream.getTest();
    s1.setName("张孝祥 2");
    System.out.println(s1.getName());
    s.getInfo();
    s1.getInfo();
    if (s == s1) {
    System.out.println("创建的是同一个实例");
    } else if (s != s1) {
    System.out.println("创建的不是同一个实例");
    } else {
    System.out.println("application error");
    }
    }
    }
    ////////////////////////////////////////////

    声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com