首页IT科技java多线程程序设计实验报告(Java多线程(4):ThreadLocal)

java多线程程序设计实验报告(Java多线程(4):ThreadLocal)

时间2025-05-04 20:06:24分类IT科技浏览3959
导读:您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~...

您好            ,我是湘王               ,这是我的博客园     ,欢迎您来         ,欢迎您再来~

为了提高CPU的利用率                ,工程师们创造了多线程            。但是线程们说:要有光!(为了减少线程创建(T1启动)和销毁(T3切换)的时间)       ,于是工程师们又接着创造了线程池ThreadPool               。就这样就可以了吗——不      ,工程师们并不满足于此                 ,他们不把自己创造出来的线程给扒个底朝天决不罢手     。

有了线程关键字解决线程安全问题         ,有了线程池解决效率问题   ,那还有什么问题是可以需要被解决的呢——还真被这帮疯子攻城狮给找到了!

当多个线程共享同一个资源的时候                  ,为了保证线程安全            ,有时不得不给资源加锁,例如使用Synchronized关键字实现同步锁         。这本质上其实是一种时间换空间的搞法——用单一资源让不同的线程依次访问               ,从而实现内容安全可控                。就像这样:

但是               ,可以不可以反过来   ,将资源拷贝成多份副本的形式来同时访问            ,达到一种空间换时间的效果呢?当然可以               ,就像这样:

而这     ,就是ThreadLocal最核心的思想       。

但这种方式在很多应用级开发的场景中用得真心不多         ,而且有些公司还禁止使用ThreadLocal                ,因为它搞不好还会带来一些负面影响      。

其实       ,从拷贝若干副本这种功能来看      ,ThreadLocal是实现了在线程内部存储数据的能力的                 ,而且相互之间还能通信                 。就像这样:

还是以代码的形式来解读一下ThreadLocal         。有一个资源类Resource:

分别有ResuorceUtils1            、ResuorceUtils2ResuorceUtils3分别以不同的方式来连接资源         ,那么看看效率如何   。

/** * 连接资源工具类   ,通过静态方式获得连接 * * @author 湘王 */ public class ResourceUtils1 { // 定义一个静态连接资源 private static Resource resource = null; // 获取连接资源 public static Resource getResource() { if(resource == null) { resource = new Resource("xiangwang", "123456"); } return resource; } // 关闭连接资源 public static void closeResource() { if(resource != null) { resource = null; } } } /** * 连接资源工具类                  ,通过实例化方式获得连接 * * @author 湘王 */ public class ResourceUtils2 { // 定义一个连接资源 private Resource resource = null; // 获取连接资源 public Resource getResource() { if(resource == null) { resource = new Resource("xiangwang", "123456"); } return resource; } // 关闭连接资源 public void closeResource() { if(resource != null) { resource = null; } } } /** * 连接资源工具类            ,通过线程中的static Connection的副本方式获得连接 * * @author 湘王 */ public class ResourceUtils3 { // 定义一个静态连接资源 private static Resource resource = null; private static ThreadLocal<Resource> resourceContainer = new ThreadLocal<Resource>(); // 获取连接资源 public static Resource getResource() { synchronized(ResourceManager.class) { resource = resourceContainer.get(); if(resource == null) { resource = new Resource("xiangwang", "123456"); resourceContainer.set(resource); } return resource; } } // 关闭连接资源 public static void closeResource() { if(resource != null) { resource = null; resourceContainer.remove(); } } } /** * 连接资源管理类 * * @author 湘王 */ public class ResourceManager { public void insert() { // 获取连接 // System.out.println("Dao.insert()-->" + Thread.currentThread().getName() + ResourceUtils1.getResource()); // Resource resource = new ResourceUtils2().getResource(); Resource resource = ResourceUtils3.getResource(); System.out.println("Dao.insert()-->" + Thread.currentThread().getName() + resource); } public void delete() { // 获取连接 // System.out.println("Dao.delete()-->" + Thread.currentThread().getName() + ResourceUtils1.getResource()); // Resource resource = new ResourceUtils2().getResource(); Resource resource = ResourceUtils3.getResource(); System.out.println("Dao.delete()-->" + Thread.currentThread().getName() + resource); } public void update() { // 获取连接 // System.out.println("Dao.update()-->" + Thread.currentThread().getName() + ResourceUtils1.getResource()); // Resource resource = new ResourceUtils2().getResource(); Resource resource = ResourceUtils3.getResource(); System.out.println("Dao.update()-->" + Thread.currentThread().getName() + resource); } public void select() { // 获取连接 // System.out.println("Dao.select()-->" + Thread.currentThread().getName() + ResourceUtils1.getResource()); // Resource resource = new ResourceUtils2().getResource(); Resource resource = ResourceUtils3.getResource(); System.out.println("Dao.select()-->" + Thread.currentThread().getName() + resource); } public void close() { ResourceUtils3.closeResource(); } public static void main(String[] args) { for (int i = 0; i < 3; i++) { new Thread(new Runnable() { ResourceManager rm = new ResourceManager(); @Override public void run() { rm.insert(); rm.delete(); rm.update(); rm.select(); rm.close(); } }).start(); } } }

执行ResourceManager类中的main()方法后,可以清楚地看到:

第一种静态方式:大部分资源都能复用               ,但毫无规律;

第二种实例方式:即使是同一个线程               ,资源实例也不一样;

第三种ThreadLocal静态方式:相同的线程有相同的实例                  。

结论是:ThreadLocal实现了线程的资源复用            。

也可以通过画图的方式来看清楚三者之间的不同:

这是静态方式下的资源管理:

这是实例方式下的资源管理:

这是ThreadLocal静态方式下的资源管理:

理解了之后   ,再来看一个数据传递的例子            ,也就是ThreadLocal实现线程间通信的例子:

/** * 数据传递 * * @author 湘王 */ public class DataDeliver { static class Data1 { public void process() { Resource resource = new Resource("xiangwang", "123456"); //将对象存储到ThreadLocal ResourceContextHolder.holder.set(resource); new Data2().process(); } } static class Data2 { public void process() { Resource resource = ResourceContextHolder.holder.get(); System.out.println("Data2拿到数据: " + resource.getName()); new Data3().process(); } } static class Data3 { public void process() { Resource resource = ResourceContextHolder.holder.get(); System.out.println("Data3拿到数据: " + resource.getName()); } } static class ResourceContextHolder { public static ThreadLocal<Resource> holder = new ThreadLocal<>(); } public static void main(String[] args) { new Data1().process(); } }

运行代码之后               ,可以看到Data1的数据都被Data2Data3拿到了     ,就像这样:

ThreadLocal在实际应用级开发中较少使用         ,因为容易造成OOM:

1               、由于ThreadLocal是一个弱引用(WeakReference<ThreadLocal<?>>)                ,因此会很容易被GC回收;

2     、ThreadLocalMap的生命周期和Thread相同       ,这就会造成当key=null时      ,value却还存在                 ,造成内存泄漏。所以         ,使用完ThreadLocal后需要显式调用remove操作(但很多码农不知道这一点)               。

感谢您的大驾光临!咨询技术         、产品                、运营和管理相关问题   ,请关注后留言               。欢迎骚扰                  ,不胜荣幸~

声明:本站所有文章            ,如无特殊说明或标注,均为本站原创发布   。任何个人或组织               ,在未征得本站同意时               ,禁止复制       、盗用      、采集                 、发布本站内容到任何网站         、书籍等各类媒体平台            。如若本站内容侵犯了原著者的合法权益   ,可联系我们进行处理               。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
哪个可以玩游戏赚钱(哪些平台可以玩游戏赚钱-下载赚钱玩也赚钱,这款赛车手游空降畅销榜第三)