一個JAVA單例模式的典型錯誤應用的分析和解決方法
阿新 • • 發佈:2018-12-22
問題來自論壇,
其程式碼如下:
[java] view plain copy print?- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import com.cfd.drp.utils.Utils;
- publicclass ClientManager {
- // 此處使用了例項級的屬性
- StringBuffer sb = new StringBuffer();
- // 此處實現了單例模式
- private
- private ClientManager() {
- }
- publicstatic ClientManager getInstance() {
- return manager;
- }
- // 這裡沒有同步,多個執行緒將同時呼叫這個方法
- public String showTree() {
- Connection connection = null;
- sb.delete(0, sb.length());
- try {
- connection = Utils.getConnection();
- tree(connection, 0, 1);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- Utils.close(connection);
- }
- return sb.toString();
- }
- publicvoid tree(Connection connection, int id, int level) throws SQLException {
- String sql = "select * from t_client where pid = ?"
- int i = 0;
- PreparedStatement ps = null;
- ResultSet rs = null;
- try {
- ps = connection.prepareStatement(sql);
- ps.setInt(1, id);
- rs = ps.executeQuery();
- while (rs.next()) {
- sb.append(rs.getString("name") + "<br>" + "/n");
- if (rs.getString("is_leaf").equals("N")) {
- tree(connection, rs.getInt("id"), level);
- }
- }
- } finally {
- Utils.slose(rs);
- Utils.close(ps);
- }
- }
- }
具體的錯誤我已經在程式碼裡標註出來了。
單例,就是系統只有一份例項,那麼多個執行緒使用這一個例項,當然也就同時使用這一個StringBuffer了。
大家一起胡亂的往裡面傾倒垃圾,怎麼可能不混亂呢!
解決方法就是將StringBuffer做成區域性變數
[java] view plain copy print?- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import com.cfd.drp.utils.Utils;
- publicclass ClientManager {
- // 此處實現了單例模式
- privatestatic ClientManager manager = new ClientManager();
- private ClientManager() {
- }
- publicstatic ClientManager getInstance() {
- return manager;
- }
- // 這裡沒有同步,多個執行緒將同時呼叫這個方法
- public String showTree() {
- // 此處使用區域性變數
- StringBuffer sb = new StringBuffer();
- Connection connection = null;
- try {
- connection = Utils.getConnection();
- tree(connection, 0, 1, sb); // 作為引數呼叫
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- Utils.close(connection);
- }
- return sb.toString();
- }
- publicvoid tree(Connection connection, int id, int level, StringBuffer sb) throws SQLException {
- String sql = "select * from t_client where pid = ?";
- int i = 0;
- PreparedStatement ps = null;
- ResultSet rs = null;
- try {
- ps = connection.prepareStatement(sql);
- ps.setInt(1, id);
- rs = ps.executeQuery();
- while (rs.next()) {
- sb.append(rs.getString("name") + "<br>" + "/n");
- if (rs.getString("is_leaf").equals("N")) {
- tree(connection, rs.getInt("id"), level,sb);
- }
- }
- } finally {
- Utils.slose(rs);
- Utils.close(ps);
- }
- }
- }