0%

【JavaWeb】ThreadLocal

ThreadLocal学习


1 ThreadLocal介绍

  • ThreadLocal类似Map集合,key-value的数据结构,但ThreadLocal根据当前线程作为key
    1
    2
    3
    4
    5
    6
    7
    8
    /** 为当前线程关联一个数据 */
    public void set(T value)

    /** 获取当前线程关联的数据 */
    public T get();

    /** 移除当前线程关联的数据 */
    public void remove()
  • 特点
  • 每一个ThreadLocal对象,只能为当前线程关联一个数据
  • ThreadLocal对象定义时,一般都是static类型
  • ThreadLocal中保存的数据,在线程销毁后,会由JVM自动释放

2 ThreadLocal实现事务

  • (1)JDBC工具类

    • 用ThreadLocal为每个线程分配一个数据库连接
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      public class JdbcUtils {
      private static DataSource dataSource;

      private static ThreadLocal<Connection> connes = new ThreadLocal<>();

      // 初始化
      static {
      Properties properties = new Properties();
      try {
      properties.load(JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties"));
      dataSource = DruidDataSourceFactory.createDataSource(properties);
      } catch (Exception e) {
      System.out.println("log --- 数据库初始化失败!");
      e.printStackTrace();
      }
      }

      /**
      * 获取连接
      * @return connection
      */
      public static Connection getConnection() {
      // 获取当前线程conn,不存在则创建
      Connection conn = connes.get();
      if(conn == null) {
      try {
      conn = dataSource.getConnection();
      conn.setAutoCommit(false); // 手动提交事务
      connes.set(conn); // 当前线程存储连接
      } catch (SQLException throwables) {
      System.out.println("log --- 获取连接失败!");
      throwables.printStackTrace();
      }
      }
      return conn;
      }

      /**
      * 提交事务,并关闭连接
      */
      public static void commitAndClose() {
      Connection conn = connes.get();
      if (conn != null) {
      try {
      conn.commit();
      } catch (SQLException throwables) {
      throwables.printStackTrace();
      } finally {
      try {
      conn.close();
      } catch (SQLException throwables) {
      throwables.printStackTrace();
      }
      connes.remove();
      }
      }
      }

      /**
      * 回滚事务,并关闭连接
      */
      public static void rollbackAndClose() {
      Connection conn = connes.get();
      if (conn != null) {
      try {
      conn.rollback();
      } catch (SQLException throwables) {
      throwables.printStackTrace();
      } finally {
      try {
      conn.close();
      } catch (SQLException throwables) {
      throwables.printStackTrace();
      }
      connes.remove();
      }
      }
      }
      }
  • (2)事务过滤器

    • 过滤器直接放行请求,执行无异常,调用工具类的提交方法;出现异常,调用工具类的回滚方法
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      public class TransactionFilter implements Filter{

      @Override
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
      try {
      chain.doFilter(request, response);
      //事务提交
      JdbcUtils.commitAndClose();
      } catch (Exception e) {
      e.printStackTrace();
      // 事务回滚
      JdbcUtils.rollbackAndClose();
      throw new RuntimeException(e);
      }
      }
      }