JAVA网关如何做线程池隔离 java线程隔离详解 |
您所在的位置:网站首页 › 线程池如何保证线程存活 › JAVA网关如何做线程池隔离 java线程隔离详解 |
文章目录1. ThreadLocal的使用示例2. ThreadLocal的使用场景2.1 线程隔离的数据库连接与事务2.2 线程隔离的session会话3. ThreadLocal原理4. ThreadLocal与内存泄露4.1 Java语言将Entry设计为弱引用4.2 记得手动remove总结
在多线程并发环境中,要保证线程并发安全总体有2类方法。 使用锁,在访问资源时是互斥的、原子性的。这个锁可以是Synchronized方法 或 Lock。或者CAS方式的乐观锁。使用线程隔离的方法。变量在线程内部,在实际运行过程中只有这个线程可以读取。变量在线程外部定义,但是每个线程只能操作属于该线程的变量副本。即 ThreadLocal类型的变量。1. ThreadLocal的使用示例定义了两个ThreadLocal类型的变量,线程t1设置的值,对于线程t2是不可见的。 public class ThreadLocalTest1 { private static ThreadLocal thl1 = new ThreadLocal(); private static ThreadLocal thl2 = new ThreadLocal(); public static void main(String[] args) { Thread t1 = new Thread(()->{ thl1.set("abc"); thl2.set(12); thl1.remove(); thl2.remove(); System.out.println(thl1.get()+","+ thl2.get()); }); Thread t2 = new Thread(()->{ System.out.println(thl1.get()+","+ thl2.get()); }); t1.start(); t2.start(); } }运行结果: 2. ThreadLocal的使用场景2.1 线程隔离的数据库连接与事务定义一个数据库连接,每个线程拿到的数据库连接都是本线程对应的数据库连接。 public class ConnectionManager { private static final ThreadLocal dbConnectionLocal = new ThreadLocal() { @Override //初始化数据。 //延迟调用方法,在线程第一次调用get或set时才执行,并且只执行1次。默认返回null。 protected Connection initialValue() { try { return DriverManager.getConnection(); } catch (SQLException e) { e.printStackTrace(); } return null; } }; public Connection getConnection() { return dbConnectionLocal.get(); } }2.2 线程隔离的session会话在每个线程session会话都是本线程对应的session。 private static final ThreadLocal threadSession = new ThreadLocal(); public static Session getSession() { Session s = (Session) threadSession.get(); try { if (s == null) { s = getSessionFactory().openSession(); threadSession.set(s); } } catch (Exception ex) { } return s; }3. ThreadLocal原理Thread类内部定义了一个ThreadLocalMap 对象ThreadLocal.ThreadLocalMap threadLocals = null;当线程调用threadlocal对象的set(Object o)和get方法时,实际上是维护ThreadLocalMap对象。如果这个对象尚未初始化,则初始化set时,以threadlocal对象为key,o 为value。get时,以threadlocal对象为key取出value。举例说明: thl1.set("abc");thl2.set(12);两条命令会在线程内的ThreadLocalMap对象上插入两条记录,这两条记录的key分别是thl1,thl2。值分别是"abc",12。 thl1.get(); thl2.get();命令执行时,实际上会在当前线程内的ThreadLocalMap对象上,查找key为thl1、thl2的值。也就是说,每个线程内部其实都有一个专属的“记录”——ThreadLocalMap,当写入和读取时,都会以threadlocal对象的引用为key,去存储读取。4. ThreadLocal与内存泄露内存泄露是指内存空间不可用,即使jvm进行垃圾回收也无法有效回收垃圾。 4.1 Java语言将Entry设计为弱引用设想:当线程内对ThreadLocal对象使用方法完毕后,此时没有对象指向ThreadLocal对象,按理说这个对象可以被回收了。但是由于ThreadLocalMap里以key,value的形式存储了ThreadLocal对象。导致仍然有链接指向ThreadLocal对象,不能被回收。 因此,Java语言将Entry类设置为弱引用,当线程内对ThreadLocal对象使用方法完毕后,JVM可以在垃圾回收时,清除ThreadLocalMap内的无效Entry对象。 static class Entry extends WeakReference |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |