ThreadLocal封装connection--隔离了相关资源,防止线程安全问题

来源:互联网 发布:工商银行博士后 知乎 编辑:程序博客网 时间:2024/05/17 03:33
线程安全问题的2种解决方法:
 
同步synchronized ,是一把锁,线程A操作变量X的时候,这把锁会锁住,此时其他线程B无法操作。
等线程A操作结束,锁打开,此时变量X可以被线程B操作 ----- 效果:多线程共享资源(变量)
 
另外,ThreadLocal是线程的本地变量,ThreadLocal隔离了相关资源,可以防止线程安全问题。---- 效果:一个线程对应一个ThreadLocal(独享资源),多线程不能共享资源(ThreadLocal可用于封装connection)
 

package com.qdsx.drp.util;

 

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

 

publicclass ConnectionManager {

   

   //ThreadLocal

   privatestatic ThreadLocal<Connection>connectionHolder =new ThreadLocal<Connection>();

   

   /**

    * 得到Connection

    * @return

    */

   publicstatic Connection getConnection(){

      

      //ThreadLocal

      Connection conn = connectionHolder.get();

      

      //ThreadLocal,如果在当前线程中没有绑定相应的Connection

      if(conn ==null){

          //取得jdbc配置信息

          try {

             JdbcInfo jdbcInfo = ConfigReader.getInstance().getJdbcInfo();

             Class.forName(jdbcInfo.getDriverName()).newInstance();

             conn = DriverManager.getConnection(jdbcInfo.getUrl(), jdbcInfo.getUsername(), jdbcInfo.getPassword());

             

             //ThreadLocal,将Connection设置(set)到线程变量(connectionHolder)中

             connectionHolder.set(conn);

             

          } catch (InstantiationException e) {

             e.printStackTrace();

             thrownew ApplicationException("系统错误,请联系系统管理员,qq:472989050");

          } catch (IllegalAccessException e) {

             e.printStackTrace();

             thrownew ApplicationException("系统错误,请联系系统管理员,qq:472989050");

          } catch (ClassNotFoundException e) {

             e.printStackTrace();

             thrownew ApplicationException("系统错误,请联系系统管理员,qq:472989050");

          } catch (SQLException e) {

             e.printStackTrace();

             thrownew ApplicationException("系统错误,请联系系统管理员,qq:472989050");

          }

      }

      return conn;     

   }

   

   publicstaticvoid closeConnection(){

      Connection conn = connectionHolder.get();

      if(conn !=null){

          try {

             conn.close();

             //ThreadLocal中清除Connection(如果不清楚,下次拿到的还是已经closeConnection,用不了)

             connectionHolder.remove();

          } catch (SQLException e) {

             e.printStackTrace();

          }

      }

   }

   

   //以下是事务处理的封装

   publicstaticvoid beginTransaction(Connection conn) {

      try {

          if(conn !=null){

             if(conn.getAutoCommit()){

                 conn.setAutoCommit(false);//手动提交

             }

          }

      } catch (SQLException e) {

          e.printStackTrace();

      }

   }

   

   publicstaticvoid commitTransaction(Connection conn) {

      try {

          if(conn !=null){

             if(!conn.getAutoCommit()){

                 conn.commit();

             }

          }

      } catch (SQLException e) {

          e.printStackTrace();

      }

   }

   

   publicstaticvoid rollbackTransaction(Connection conn) {

      try {

          if (conn !=null) {

             if(!conn.getAutoCommit()){

                 conn.rollback();

             }

          }

      } catch (SQLException e) {

          e.printStackTrace();

      }

   }

   

   publicstaticvoid resetConnection(Connection conn) {

      try {

          if(conn !=null){

             if(conn.getAutoCommit()){

                 conn.setAutoCommit(false);

             }else{

                 conn.setAutoCommit(true);

             }

          }

      } catch (SQLException e) {

          e.printStackTrace();

      }

   }

   

   publicstaticvoid setAutoCommit(Connection conn,boolean autoCommit) {

      if (conn !=null) {

          try {

             conn.setAutoCommit(autoCommit);

          } catch (SQLException e) {

             e.printStackTrace();

          }

      }

   }  

}

 
在service层的使用:
 

   publicvoid addFlowCard(FlowCard flowCard)throws ApplicationException {

      Connection conn = null;

      try {

          //取得

          conn = ConnectionManager.getConnection();

          

          //开启事务

          ConnectionManager.beginTransaction(conn);

          

          //生成流向单单号

          String flowCardVouNo = flowCardDao.generateVouNo();

          //添加流向单主信息

          flowCardDao.addFlowCardMaster(flowCardVouNo, flowCard);

          //添加流向单明细信息

          flowCardDao.addFlowCardDetail(flowCardVouNo, flowCard.getFlowCardDetailList());

      

          //提交事务

          ConnectionManager.commitTransaction(conn);

      } catch (DaoException e) {

          //异常,回滚事务

          ConnectionManager.rollbackTransaction(conn);

          e.printStackTrace();

          thrownew ApplicationException("添加流向单失败!");

      }finally{

          //关闭Connection,并从ThreadLocal中清除Connection

          ConnectionManager.closeConnection();

      }     

   }

 

 

在dao层使用:

   public StringgenerateVouNo() throws DaoException {

      Connection conn = ConnectionManager.getConnection();

      returnnull;

   }

 

   publicvoid addFlowCardMaster(String flowCardVouNo, FlowCard flowCard)

          throws DaoException {

      Connection conn = ConnectionManager.getConnection();

   }

 

   publicvoid addFlowCardDetail(String flowCardVouNo,

          List<FlowCardDetail> flowCardDetailList) throws DaoException {

      Connection conn = ConnectionManager.getConnection();

   }