您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~
为了提高CPU的利用率,工程师们创造了多线程 。但是线程们说:要有光?。ㄎ思跎傧叱檀唇ǎ═1启动)和销毁(T3切换)的时间),于是工程师们又接着创造了线程池ThreadPool 。就这样就可以了吗?——不,工程师们并不满足于此,他们不把自己创造出来的线程给扒个底朝天决不罢手 。
有了线程关键字解决线程安全问题,有了线程池解决效率问题,那还有什么问题是可以需要被解决的呢?——还真被这帮疯子攻城狮给找到了!
当多个线程共享同一个资源的时候,为了保证线程安全,有时不得不给资源加锁,例如使用Synchronized关键字实现同步锁 。这本质上其实是一种时间换空间的搞法——用单一资源让不同的线程依次访问,从而实现内容安全可控 。就像这样:
文章插图
但是,可以不可以反过来 , 将资源拷贝成多份副本的形式来同时访问,达到一种空间换时间的效果呢?当然可以,就像这样:
文章插图
而这,就是ThreadLocal最核心的思想 。
【4 Java多线程:ThreadLocal】但这种方式在很多应用级开发的场景中用得真心不多 , 而且有些公司还禁止使用ThreadLocal,因为它搞不好还会带来一些负面影响 。
其实,从拷贝若干副本这种功能来看,ThreadLocal是实现了在线程内部存储数据的能力的,而且相互之间还能通信 。就像这样:
文章插图
还是以代码的形式来解读一下ThreadLocal 。有一个资源类Resource:
/** * 资源类 * * @author 湘王 */public class Resource { private String name; private String value; public Resource(String name, String value) { super(); this.name = name; this.value = value; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getValue() { return value; } public void setValue(String value) { this.value = value; }}分别有ResuorceUtils1、ResuorceUtils2和ResuorceUtils3分别以不同的方式来连接资源,那么看看效率如何 。
/** * 连接资源工具类,通过静态方式获得连接 * * @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(); } }}
推荐阅读
- SpringCloud怎么迈向云原生?
- 华为freebuds4i使用方法_华为freebuds4i怎么重新配对
- DNF如何升冒险团等级(dnf冒险团40级要多少号)
- javascript编程单线程之异步模式Asynchronous
- Java 8 Time API
- 3050和3050ti的差距_3050和3050ti差多少
- 多可用区 亚马逊云 RDB数据故障转移
- realmev11多少钱_真我v11手机多少钱
- 洛克王国雪顶妖兽进化概率是多少
- vivox60pro+支持无线充电吗_vivox60pro+电池容量是多少