Open fred-ye opened 10 years ago
最近在看Universal-Image-Loader源码的时候又碰到了ThreadLocal,依稀记得以前用ThreadLocal写过点东西,于是翻看一下以前的笔记回顾一下,在此处也记录一下。
ThreadLocal,线程局部变量,用来保存与当前线程绑定的一些数据。java规范里面是这么说的。ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread。在类中ThreadLocal的实例通常是private static的 用来与线程绑定,一个线程一个。我们主要是使用里面的get()和set()方法。
ThreadLocal
ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread
ThreadLocal中的方法get()和set(T value)方法实际上都是对当前Thread类中的一个Map进行操作。我们可以看到在Thread类中维护着这么一个Map。该Map的类型是ThreadLocal类中的一个静态内部类。
get()
set(T value)
/* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null;
根据ThreadLocal是线程独享的这个特性。我们可以利用ThreadLocal中的set(T value)方法将一个与数据库的连接设置进去。那么就可以保证每一个线程一个连接。(数据库连接不能在线程间共享【连接时线程不安全的】,会破坏事务的原子性和隔离性。)
直接上代码:
public class JdbcUtil { // 该集合用来保存数据的. private static Properties info = new Properties(); static { try { InputStream is = JdbcUtil.class .getResourceAsStream("/cfg/config.properties"); // 用info调用load()方法,可完成读文件,解析字符串等任务,并将内容添加到集合中。 info.load(is); // 用了io流之后,一定要记得关流. is.close(); } catch (Exception e) { // 在静态代码块中只能抛出这一个异常。ExceptionInInitializerError(e); throw new ExceptionInInitializerError(e); } } /* * 注:tl 是final,保证其不会指向其它的对象。ThreadLocal的实例通常都是private static final * 一个线程一个数据库连接。 */ private static final ThreadLocal<Connection> tl = new ThreadLocal<Connection>(); public static Connection getConnection() throws Exception { // 刚开始由于没有设置值,所以拿到的是null. tl.get()返回的是一个对象。 Connection conn = tl.get(); if (conn == null) { Class.forName(info.getProperty("driver")); conn = DriverManager.getConnection(info.getProperty("url"), info.getProperty("username"), info.getProperty("password")); // 将连接放到ThreadLocal中。 tl.set(conn); } return conn; } // 释放资源。但是有一点不完整。如果在加一个参数PreparedStatement pstm,那就完善了。 public static void release(ResultSet rs, Statement stm, Connection conn) { if (rs != null) try { rs.close(); } catch (Exception e) { e.printStackTrace(); } if (stm != null) try { stm.close(); } catch (Exception e) { e.printStackTrace(); } if (conn != null) try { conn.close(); } catch (Exception e) { e.printStackTrace(); } } //为了测试方便就把测试方法写在这了。 public static void main(String args[]) throws Exception { System.out.println(getConnection()); } }
最近在看Universal-Image-Loader源码的时候又碰到了ThreadLocal,依稀记得以前用ThreadLocal写过点东西,于是翻看一下以前的笔记回顾一下,在此处也记录一下。
原理
ThreadLocal
,线程局部变量,用来保存与当前线程绑定的一些数据。java规范里面是这么说的。ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread
。在类中ThreadLocal的实例通常是private static的 用来与线程绑定,一个线程一个。我们主要是使用里面的get()和set()方法。ThreadLocal中的方法
get()
和set(T value)
方法实际上都是对当前Thread类中的一个Map进行操作。我们可以看到在Thread类中维护着这么一个Map。该Map的类型是ThreadLocal
类中的一个静态内部类。应用
根据
ThreadLocal
是线程独享的这个特性。我们可以利用ThreadLocal中的set(T value)方法将一个与数据库的连接设置进去。那么就可以保证每一个线程一个连接。(数据库连接不能在线程间共享【连接时线程不安全的】,会破坏事务的原子性和隔离性。)直接上代码: