毕业设计餐饮网站建设,网站的搭建流程,网站下载软件入口,江苏网站seo一、对ThreadLocal的理解
ThreadLocal#xff0c;很多地方叫做线程本地变量#xff0c;也有些地方叫做线程本地存储#xff0c;其实意思差不多。可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本#xff0c;那么每个线程可以访问自己内部的副本变量。这句…一、对ThreadLocal的理解
ThreadLocal很多地方叫做线程本地变量也有些地方叫做线程本地存储其实意思差不多。可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本那么每个线程可以访问自己内部的副本变量。这句话从字面上看起来很容易理解但是真正理解并不是那么容易。
ThreadLocal的官方API解释为
“该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物因为访问某个变量通过其 get 或 set 方法的每个线程都有自己的局部变量它独立于变量的初始化副本。ThreadLocal 实例通常是类中的 private static 字段它们希望将状态与某一个线程例如用户 ID 或事务 ID相关联。”
大概的意思有两点
1、ThreadLocal提供了一种访问某个变量的特殊方式访问到的变量属于当前线程即保证每个线程的变量不一样而同一个线程在任何地方拿到的变量都是一致的这就是所谓的线程隔离。
2、如果要使用ThreadLocal通常定义为private static类型在我看来最好是定义为private static final类型。 很多博客都这样说ThreadLocal为解决多线程程序的并发问题提供了一种新的思路ThreadLocal的目的是为了解决多线程访问资源时的共享问题。如果你也这样认为的那现在给你10秒钟清空之前对ThreadLocal的错误的认知ThreadLocal可以总结为一句话ThreadLocal的作用是提供线程内的局部变量这种变量在线程的生命周期内起作用减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。我们还是先来看一个例子
class ConnectionManager {private static Connection connect null;public static Connection openConnection() {if(connect null){connect DriverManager.getConnection();}return connect;}public static void closeConnection() {if(connect!null)connect.close();}
}
假设有这样一个数据库链接管理类这段代码在单线程中使用是没有任何问题的但是如果在多线程中使用呢很显然在多线程中使用会存在线程安全问题第一这里面的2个方法都没有进行同步很可能在openConnection方法中会多次创建connect第二由于connect是共享变量那么必然在调用connect的地方需要使用到同步来保障线程安全因为很可能一个线程在使用connect进行数据库操作而另外一个线程调用closeConnection关闭链接。 所以出于线程安全的考虑必须将这段代码的两个方法进行同步处理并且在调用connect的地方需要进行同步处理。这样将会大大影响程序执行效率因为一个线程在使用connect进行数据库操作的时候其他线程只有等待。 那么大家来仔细分析一下这个问题这地方到底需不需要将connect变量进行共享事实上是不需要的。假如每个线程中都有一个connect变量各个线程之间对connect变量的访问实际上是没有依赖关系的即一个线程不需要关心其他线程是否对这个connect进行了修改的。 到这里可能会有朋友想到既然不需要在线程之间共享这个变量可以直接这样处理在每个需要使用数据库连接的方法中具体使用时才创建数据库链接然后在方法调用完毕再释放这个连接。比如下面这样
class ConnectionManager {private Connection connect null;public Connection openConnection() {if(connect null){connect DriverManager.getConnection();}return connect;}public void closeConnection() {if(connect!null)connect.close();}
}class Dao{public void insert() {ConnectionManager connectionManager new ConnectionManager();Connection connection connectionManager.openConnection();//使用connection进行操作connectionManager.closeConnection();}
}这样处理确实也没有任何问题由于每次都是在方法内部创建的连接那么线程之间自然不存在线程安全问题。但是这样会有一个致命的影响导致服务器压力非常大并且严重影响程序执行性能。由于在方法中需要频繁地开启和关闭数据库连接这样不尽严重影响程序执行效率还可能导致服务器压力巨大。 那么这种情况下使用ThreadLocal是再适合不过的了因为ThreadLocal在每个线程中对该变量会创建一个副本即每个线程内部都会有一个该变量且在线程内部任何地方都可以使用线程之间互不影响这样一来就不存在线程安全问题也不会严重影响程序执行性能。 但是要注意虽然ThreadLocal能够解决上面说的问题但是由于在每个线程中都创建了副本所以要考虑它对资源的消耗比如内存的占用会比不使用ThreadLocal要大。