如何将ThreadLocal在并发编程中实现并优化其长尾词应用场景?

2026-04-15 08:4217阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计769个文字,预计阅读时间需要4分钟。

如何将ThreadLocal在并发编程中实现并优化其长尾词应用场景?

在并发编程中,如果成员变量不做任何处理,实际上是不安全的,因为各个线程都可能操作同一个变量。在这种情况下,我们需要满足以下条件:

gistfile1.txt

在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线程都在操作同一个变量,显然是不行的。 那么在有一种情况之下,我们需要满足这样一个条件:变量是同一个,但是每个线程都使用同一个初始值,也就是使用同一个 变量的一个新的副本。这种情况之下ThreadLocal就非常使用,比如说DAO的数据库连接,我们知道DAO是单例的,那么他的属性 Connection就不是一个线程安全的变量。而我们每个线程都需要使用他,并且各自使用各自的。这种情况,ThreadLocal就比较 好的解决了这个问题。   首先定义一个ThreadLocal: public class ConnectionUtil { private static ThreadLocal tl = new ThreadLocal (); private static Connection initConn = null; static { try { initConn = DriverManager.getConnection("url, name and password"); } catch (SQLException e) { e.printStackTrace(); } } public Connection getConn() { Connection c = tl.get(); if(null == c) tl.set(initConn); return tl.get(); } }   这样子,都是用同一个连接,但是每个连接都是新的,是同一个连接的副本。   那么实现机制是如何的呢?   1、每个Thread对象内部都维护了一个ThreadLocalMap这样一个ThreadLocal的Map,可以存放若干个ThreadLocal。 /* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null;   2、当我们在调用get()方法的时候,先获取当前线程,然后获取到当前线程的ThreadLocalMap对象,如果非空,那么取出 ThreadLocal的value,否则进行初始化,初始化就是将initialValue的值set到ThreadLocal中。 public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue(); }   3、当我们调用set()方法的时候,很常规,就是将值设置进ThreadLocal中。   4、总结:当我们调用get方法的时候,其实每个当前线程中都有一个ThreadLocal。每次获取或者设置都是对该 ThreadLocal进行的操作,是与其他线程分开的。   5、应用场景:当很多线程需要多次使用同一个对象,并且需要该对象具有相同初始化值的时候最适合使用ThreadLocal。   事实上,从本质来讲,就是每个线程都维护了一个map,而这个map的key就是threadLocal,而值就是我们set的那个值, 每次线程在get的时候,都从自己的变量中取值,既然从自己的变量中取值,那肯定就不存在线程安全问题,总体来讲, ThreadLocal这个变量的状态根本没有发生变化,他仅仅是充当一个key的角色,另外提供给每一个线程一个初始值。如果允许 的话,我们自己就能实现一个这样的功能,只不过恰好JDK就已经帮我们做了这个事情。

如何将ThreadLocal在并发编程中实现并优化其长尾词应用场景?

本文共计769个文字,预计阅读时间需要4分钟。

如何将ThreadLocal在并发编程中实现并优化其长尾词应用场景?

在并发编程中,如果成员变量不做任何处理,实际上是不安全的,因为各个线程都可能操作同一个变量。在这种情况下,我们需要满足以下条件:

gistfile1.txt

在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线程都在操作同一个变量,显然是不行的。 那么在有一种情况之下,我们需要满足这样一个条件:变量是同一个,但是每个线程都使用同一个初始值,也就是使用同一个 变量的一个新的副本。这种情况之下ThreadLocal就非常使用,比如说DAO的数据库连接,我们知道DAO是单例的,那么他的属性 Connection就不是一个线程安全的变量。而我们每个线程都需要使用他,并且各自使用各自的。这种情况,ThreadLocal就比较 好的解决了这个问题。   首先定义一个ThreadLocal: public class ConnectionUtil { private static ThreadLocal tl = new ThreadLocal (); private static Connection initConn = null; static { try { initConn = DriverManager.getConnection("url, name and password"); } catch (SQLException e) { e.printStackTrace(); } } public Connection getConn() { Connection c = tl.get(); if(null == c) tl.set(initConn); return tl.get(); } }   这样子,都是用同一个连接,但是每个连接都是新的,是同一个连接的副本。   那么实现机制是如何的呢?   1、每个Thread对象内部都维护了一个ThreadLocalMap这样一个ThreadLocal的Map,可以存放若干个ThreadLocal。 /* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null;   2、当我们在调用get()方法的时候,先获取当前线程,然后获取到当前线程的ThreadLocalMap对象,如果非空,那么取出 ThreadLocal的value,否则进行初始化,初始化就是将initialValue的值set到ThreadLocal中。 public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue(); }   3、当我们调用set()方法的时候,很常规,就是将值设置进ThreadLocal中。   4、总结:当我们调用get方法的时候,其实每个当前线程中都有一个ThreadLocal。每次获取或者设置都是对该 ThreadLocal进行的操作,是与其他线程分开的。   5、应用场景:当很多线程需要多次使用同一个对象,并且需要该对象具有相同初始化值的时候最适合使用ThreadLocal。   事实上,从本质来讲,就是每个线程都维护了一个map,而这个map的key就是threadLocal,而值就是我们set的那个值, 每次线程在get的时候,都从自己的变量中取值,既然从自己的变量中取值,那肯定就不存在线程安全问题,总体来讲, ThreadLocal这个变量的状态根本没有发生变化,他仅仅是充当一个key的角色,另外提供给每一个线程一个初始值。如果允许 的话,我们自己就能实现一个这样的功能,只不过恰好JDK就已经帮我们做了这个事情。

如何将ThreadLocal在并发编程中实现并优化其长尾词应用场景?