一个JAVA单例模式的典型错误应用的分析和解决方法

来源:互联网 发布:linux用ftp上传文件 编辑:程序博客网 时间:2024/06/03 20:54

问题来自论坛,

http://topic.csdn.net/u/20090927/23/497372f4-af98-4b7b-8489-3eb3a8de43b5.html

 

其代码如下:

[java] view plaincopy
  1. import java.sql.Connection;  
  2. import java.sql.PreparedStatement;  
  3. import java.sql.ResultSet;  
  4. import java.sql.SQLException;  
  5. import com.cfd.drp.utils.Utils;  
  6. public class ClientManager {  
  7.   // 此处使用了实例级的属性  
  8.   StringBuffer sb = new StringBuffer();  
  9.   // 此处实现了单例模式  
  10.   private static ClientManager manager = new ClientManager();  
  11.   private ClientManager() {  
  12.   }  
  13.   public static ClientManager getInstance() {  
  14.     return manager;  
  15.   }  
  16.   // 这里没有同步,多个线程将同时调用这个方法  
  17.   public String showTree() {  
  18.     Connection connection = null;  
  19.     sb.delete(0, sb.length());  
  20.     try {  
  21.       connection = Utils.getConnection();  
  22.       tree(connection, 01);  
  23.     } catch (Exception e) {  
  24.       e.printStackTrace();  
  25.     } finally {  
  26.       Utils.close(connection);  
  27.     }  
  28.     return sb.toString();  
  29.   }  
  30.   public void tree(Connection connection, int id, int level) throws SQLException {  
  31.     String sql = "select * from t_client where pid = ?";  
  32.     int i = 0;  
  33.     PreparedStatement ps = null;  
  34.     ResultSet rs = null;  
  35.     try {  
  36.       ps = connection.prepareStatement(sql);  
  37.       ps.setInt(1, id);  
  38.       rs = ps.executeQuery();  
  39.       while (rs.next()) {  
  40.         sb.append(rs.getString("name") + "<br>" + "/n");  
  41.         if (rs.getString("is_leaf").equals("N")) {  
  42.           tree(connection, rs.getInt("id"), level);  
  43.         }  
  44.       }  
  45.     } finally {  
  46.       Utils.slose(rs);  
  47.       Utils.close(ps);  
  48.     }  
  49.   }  
  50. }  

 

具体的错误我已经在代码里标注出来了。

单例,就是系统只有一份实例,那么多个线程使用这一个实例,当然也就同时使用这一个StringBuffer了。

大家一起胡乱的往里面倾倒垃圾,怎么可能不混乱呢!

 

解决方法就是将StringBuffer做成局部变量

[java] view plaincopy
  1. import java.sql.Connection;  
  2. import java.sql.PreparedStatement;  
  3. import java.sql.ResultSet;  
  4. import java.sql.SQLException;  
  5. import com.cfd.drp.utils.Utils;  
  6. public class ClientManager {  
  7.   // 此处实现了单例模式  
  8.   private static ClientManager manager = new ClientManager();  
  9.   private ClientManager() {  
  10.   }  
  11.   public static ClientManager getInstance() {  
  12.     return manager;  
  13.   }  
  14.   // 这里没有同步,多个线程将同时调用这个方法  
  15.   public String showTree() {  
  16.     // 此处使用局部变量  
  17.     StringBuffer sb = new StringBuffer();  
  18.     Connection connection = null;  
  19.     try {  
  20.       connection = Utils.getConnection();  
  21.       tree(connection, 01, sb); // 作为参数调用  
  22.     } catch (Exception e) {  
  23.       e.printStackTrace();  
  24.     } finally {  
  25.       Utils.close(connection);  
  26.     }  
  27.     return sb.toString();  
  28.   }  
  29.   public void tree(Connection connection, int id, int level, StringBuffer sb) throws SQLException {  
  30.     String sql = "select * from t_client where pid = ?";  
  31.     int i = 0;  
  32.     PreparedStatement ps = null;  
  33.     ResultSet rs = null;  
  34.     try {  
  35.       ps = connection.prepareStatement(sql);  
  36.       ps.setInt(1, id);  
  37.       rs = ps.executeQuery();  
  38.       while (rs.next()) {  
  39.         sb.append(rs.getString("name") + "<br>" + "/n");  
  40.         if (rs.getString("is_leaf").equals("N")) {  
  41.           tree(connection, rs.getInt("id"), level,sb);  
  42.         }  
  43.       }  
  44.     } finally {  
  45.       Utils.slose(rs);  
  46.       Utils.close(ps);  
  47.     }  
  48.   }  
  49. }  

0 0
原创粉丝点击