文档章节

ThreadLocal的应用

4rnold
 4rnold
发布于 2017/09/11 00:25
字数 569
阅读 13
收藏 0
点赞 0
评论 0

ThreadLocal 内存泄露问题

ThreadLocal本身不存储值,他只作为一个key。真正存值的是thread

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;//t.threadLocals是ThreadLocal.ThreadLocalMap类型
}

输入图片说明

也就是说,threadlocal的生命周期是一个普通的变量的生命周期,而threadLocal中存放的数据的生命周期是当前thread的生命周期(thread不销毁一直都存在)。如果遇到thread不销毁的情况,比如使用线程池,不断创建新的threadLocal作为key 向 Thread.threadLocals中插入对象,而之前的对象也不会被回收,因为有Thread.threadLocals的引用。这样会造成内存泄露。所以需要在使用完成后,手动从threadLocal中删除数据。

ThreadLocal 应用

通常我们写一个工具类都是无状态的。例如下面写一个db的工具类。

public class DatabaseHelper1 {

    private static final Logger LOGGER = LoggerFactory.getLogger(DatabaseHelper.class);
    private static final String DRIVER;
    private static final String URL;
    private static final String USERNAME;
    private static final String PASSWORD;

    static {
        Properties conf = PropsUtil.loadProps("config.properties");
        String driver = conf.getProperty("jdbc.driver");
        String url = conf.getProperty("jdbc.url");
        String username = conf.getProperty("jdbc.username");
        String password = conf.getProperty("jdbc.password");

        DRIVER = driver;
        URL = url;
        USERNAME = username;
        PASSWORD = password;
    }

  //示例代码
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(URL, USERNAME, PASSWORD);
    }

  //示例代码
    public static <T>List<T> queryEntityList(Connection connection, Class<T> entityClass, String sql, Object... params) {
        return new ArrayList<>();
    }
}

这样的话service调用就比较麻烦

    public List<Customer> getCustomerList1() throws SQLException {
        Connection connection = DatabaseHelper1.getConnection();
        String sql = "select * from customer";
        return DatabaseHelper1.queryEntityList(connection,Customer.class, sql);
    }

能不能让DatabaseHelper工具类有记忆功能?不用每次service都是先取到connection再做其他操作。threadLocal可以帮我们实现。

public class DatabaseHelper {
      private static ThreadLocal<Connection> threadConnection = new ThreadLocal<>();

      public static Connection getConnection() {
        Connection connection = threadConnection.get();
        if (connection == null) {
            try {
                connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            } catch (SQLException e) {
                LOGGER.error("get connection fail");
            } finally {
                threadConnection.set(connection);
            }
        }
        return connection;
    }
  
      public static void closeConnetion(Connection connection) {
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                LOGGER.error("close connection fail");
            } finally {
                threadConnection.remove();
            }
        }
    }
  
      public static <T> List<T> queryEntityList(Class<T> entityClass, String sql, Object... params) {
        List<T> entityList = new ArrayList<>();
        Connection connection = getConnection();
        try {
            entityList = QUERY_RUNNER.query(connection, sql, new BeanListHandler<T>(entityClass), params);
        } catch (SQLException e) {
            LOGGER.error("queryEntity fail", e);
        } finally {
            closeConnetion(connection);
        }
        return entityList;
    }
}

通过threadLocal,使service调用变的简单

public List<Customer> getCustomerList() {
   	String sql = "select * from customer";
  	return DatabaseHelper.queryEntityList(Customer.class, sql);
}

但是还记得上面提到的threadlocal内存泄露么,在每次使用完threadLocal记得将其内容删除。就是closeConnection()中的threadConnection.remove();

© 著作权归作者所有

共有 人打赏支持
4rnold
粉丝 0
博文 31
码字总数 16491
作品 0
深圳
程序员
Java就业变难了?你需要对自己有点信心

伴随着IT的火热,越来越多的人进入了IT领域,这在进一步推动着IT发展的同时也极大增加了就业压力。伴随着激烈的岗位竞争,越来越多的人开始感叹工作难找,越火的行业越是如此,Java自是首当其...

糖宝_d864 ⋅ 06/08 ⋅ 0

Oracle Java Mission Control 帮助

缩写 含义 JDK Java 开发工具包 JDP Java Discovery Protocol JFR Java 飞行记录器 JMC Java Mission Control JMX Java Management Extensions JVM Java 虚拟机 MBean 托管 Bean (Java) RCP ......

光斑 ⋅ 04/27 ⋅ 0

Java开发学习之三版本简介 java编程

  Java编程语言,在更迭迅速的互联网领域多年屹立不倒,足以得见Java这门语言旺盛的生命力,因此,会有很多想要进入互联网领域的朋友,想要学Java来转行开发。但是,所谓“隔行如隔山”,j...

老男孩Linux培训 ⋅ 06/05 ⋅ 0

Java:大数据技术领域的一匹黑马

诞生于1991年的Java如今已经成为世界范围内应用最为广泛的编程语言之一。在今天的文章中,我们将共同了解Java所拥有的七大关键新特性,展望其如何在未来的超级计算、大数据以及物联网等领域继...

Java大数据处理 ⋅ 04/22 ⋅ 0

Oracle Java SE 8 发行版更新:限制商业或生产用途

Oracle Java SE 8 发行版更新 Oracle Java SE 8 的公开更新仍面向单独的个人使用提供,至少持续至 2020 年底。 2019 年 1 月以后发布的 Oracle Java SE 8 公开更新将不向没有商用许可证的业务...

抢小孩糖吃 ⋅ 04/18 ⋅ 39

甲骨文开源Java 性能监控调试工具 JMC

JMC (Java Mission Control) 是Oracle开源的Java 性能监控调试工具, 源自 JRockit JVM , 主要由三个组件构成:Java 进程浏览器、JMX 控制台和 Java Flight 记录器。 主要特性: Java 进程浏览...

marsdream ⋅ 05/07 ⋅ 0

CentOS 6.5 安装JDK(包含卸载原有默认JDK)

卸载原有1.7 JDK 查看是否安装了JDK 若有内容就进一步查看JDK信息 卸载 安装jdk ===================================== 安装wget 新建目录 进入目录 下载JDK 安装JDK 配置环境变量 往文件内...

阿白 ⋅ 05/23 ⋅ 0

重磅!Java 性能监控调试工具 JMC 宣布开源

JRockit JVM 创始人之一、Oracle Java 产品组成员 Marcus Hirt 昨日在其博客上宣布,Java Mission Control(JMC)的源代码已正式开源。 JMC 是源自 JRockit JVM 的一套监控和管理工具,Oracl...

王练 ⋅ 05/07 ⋅ 6

Java学习---Java简单认识

前言 小编在学习Java方面的基础知识,发现里面有很多是结合之前的语言的特点发展过来的,不同的地方是,Java有它自己的发展和特点。下面小编先简单地做一下总结,结合看过的1-2章的J2SE视频,...

m18633778874 ⋅ 04/01 ⋅ 0

Java程序员必读书单,家族又添新成员

点击关注异步图书,置顶公众号 每天与你分享IT好书 技术干货 职场知识 参与文末话题讨论,每日赠送异步图书。 ——异步小编 有些革命出其不意地吸引了全世界的眼球。Twitter、Linux操作系统和...

异步社区 ⋅ 05/09 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring Boot整合模板引擎thymeleaf

项目结构 引入依赖pom.xml <!-- 引入 thymeleaf 模板依赖 --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId......

yysue ⋅ 13分钟前 ⋅ 0

ConstraintLayout使用解析

AndroidStudio3.0创建Project默认的布局就是ConstraintLayout。 AndroidStudio3.0前的可以自己修改,使用ConstraintLayout。 为了要使用ConstraintLayout,我们需要在app/build.gradle文件中...

_OUTMAN_ ⋅ 25分钟前 ⋅ 0

OSChina 周三乱弹 —— 这样的女人私生活太混乱了

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ 胖达panda :你经历过体验到人生的大起大落吗?我一朋友在10秒内体验了,哈哈。@小小编辑 请点一首《almost lover》送给他。 《almost love...

小小编辑 ⋅ 59分钟前 ⋅ 9

自己动手写一个单链表

文章有不当之处,欢迎指正,如果喜欢微信阅读,你也可以关注我的微信公众号:好好学java,获取优质学习资源。 一、概述 单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对...

公众号_好好学java ⋅ 今天 ⋅ 0

Centos7重置Mysql 8.0.1 root 密码

问题产生背景: 安装完 最新版的 mysql8.0.1后忘记了密码,向重置root密码;找了网上好多资料都不尽相同,根据自己的问题总结如下: 第一步:修改配置文件免密码登录mysql vim /etc/my.cnf 1...

豆花饭烧土豆 ⋅ 今天 ⋅ 0

熊掌号收录比例对于网站原创数据排名的影响[图]

从去年下半年开始,我在写博客了,因为我觉得业余写写博客也还是很不错的,但是从2017年下半年开始,百度已经推出了原创保护功能和熊掌号平台,为此,我也提交了不少以前的老数据,而这些历史...

原创小博客 ⋅ 今天 ⋅ 0

LVM讲解、磁盘故障小案例

LVM LVM就是动态卷管理,可以将多个硬盘和硬盘分区做成一个逻辑卷,并把这个逻辑卷作为一个整体来统一管理,动态对分区进行扩缩空间大小,安全快捷方便管理。 1.新建分区,更改类型为8e 即L...

蛋黄Yolks ⋅ 今天 ⋅ 0

Hadoop Yarn调度器的选择和使用

一、引言 Yarn在Hadoop的生态系统中担任了资源管理和任务调度的角色。在讨论其构造器之前先简单了解一下Yarn的架构。 上图是Yarn的基本架构,其中ResourceManager是整个架构的核心组件,它负...

p柯西 ⋅ 今天 ⋅ 0

uWSGI + Django @ Ubuntu

创建 Django App Project 创建后, 可以看到路径下有一个wsgi.py的问题 uWSGI运行 直接命令行运行 利用如下命令, 可直接访问 uwsgi --http :8080 --wsgi-file dj/wsgi.py 配置文件 & 运行 [u...

袁祾 ⋅ 今天 ⋅ 0

JVM堆的理解

在JVM中,我们经常提到的就是堆了,堆确实很重要,其实,除了堆之外,还有几个重要的模块,看下图: 大 多数情况下,我们并不需要关心JVM的底层,但是如果了解它的话,对于我们系统调优是非常...

不羁之后 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部