您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
三六零分类信息网 > 舟山分类信息网,免费分类信息发布

java如何使用ThreadLocal存储线程专有对象

2025/6/16 20:09:29发布7次查看
使用threadlocal存储线程专有对象threadlocal提供了线程专有对象,可以在整个线程生命周期中随时取用,极大地方便了一些逻辑的实现。
常见的threadlocal用法主要有两种:
保存线程上下文对象,避免多层级参数传递;
保存非线程安全对象,避免多线程并发调用。
1.保存线程上下文对象,避免多层级参数传递这里,以pagehelper插件的源代码中的分页参数设置与使用为例说明。
设置分页参数代码:
/** 分页方法类 */public abstract class pagemethod {    /** 本地分页 */    protected static final threadlocal<page> local_page = new threadlocal<page>();    /** 设置分页参数 */    protected static void setlocalpage(page page) {        local_page.set(page);    }    /** 获取分页参数 */    public static <t> page<t> getlocalpage() {        return local_page.get();    }    /** 开始分页 */    public static <e> page<e> startpage(int pagenum, int pagesize, boolean count, boolean reasonable, boolean pagesizezero) {        page<e> page = new page<e>(pagenum, pagesize, count);        page.setreasonable(reasonable);        page.setpagesizezero(pagesizezero);        page<e> oldpage = getlocalpage();        if (oldpage != null && oldpage.isorderbyonly()) {            page.setorderby(oldpage.getorderby());        }        setlocalpage(page);        return page;    }}
使用分页参数代码:
/** 虚辅助方言类 */public abstract class abstracthelperdialect extends abstractdialect implements constant {    /** 获取本地分页 */    public <t> page<t> getlocalpage() {        return pagehelper.getlocalpage();    }    /** 获取分页sql */    @override    public string getpagesql(mappedstatement ms, boundsql boundsql, object parameterobject, rowbounds rowbounds, cachekey pagekey) {        string sql = boundsql.getsql();        page page = getlocalpage();        string orderby = page.getorderby();        if (stringutil.isnotempty(orderby)) {            pagekey.update(orderby);            sql = orderbyparser.convertoorderbysql(sql, orderby);        }        if (page.isorderbyonly()) {            return sql;        }        return getpagesql(sql, page, pagekey);    }    ...}
使用分页插件代码:
/** 查询用户函数 */public pageinfo<userdo> queryuser(userquery userquery, int pagenum, int pagesize) {    pagehelper.startpage(pagenum, pagesize);    list<userdo> userlist = userdao.queryuser(userquery);    pageinfo<userdo> pageinfo = new pageinfo<>(userlist);    return pageinfo;}
如果要把分页参数通过函数参数逐级传给查询语句,除非修改mybatis相关接口函数,否则是不可能实现的。
2.保存非线程安全对象,避免多线程并发调用在写日期格式化工具函数时,首先想到的写法如下:
/** 日期模式 */private static final string date_pattern = yyyy-mm-dd;/** 格式化日期函数 */public static string formatdate(date date) {    return new simpledateformat(date_pattern).format(date);}
其中,每次调用都要初始化dateformat导致性能较低,把dateformat定义成常量后的写法如下:
/** 日期格式 */private static final dateformat date_format = new simpledateformat(yyyy-mm-dd);/** 格式化日期函数 */public static string formatdate(date date) {    return date_format.format(date);}
由于simpledateformat是非线程安全的,当多线程同时调用formatdate函数时,会导致返回结果与预期不一致。如果采用threadlocal定义线程专有对象,优化后的代码如下:
/** 本地日期格式 */private static final threadlocal<dateformat> local_date_format = new threadlocal<dateformat>() {    @override    protected dateformat initialvalue() {        return new simpledateformat(yyyy-mm-dd);    }};/** 格式化日期函数 */public static string formatdate(date date) {    return local_date_format.get().format(date);}
这是在没有线程安全的日期格式化工具类之前的实现方法。在jdk8以后,建议使用datetimeformatter代替simpledateformat,因为simpledateformat是线程不安全的,而datetimeformatter是线程安全的。当然,也可以采用第三方提供的线程安全日期格式化函数,比如apache的dateformatutils工具类。
注意:threadlocal有一定的内存泄露的风险,尽量在业务代码结束前调用remove函数进行数据清除。
以上就是java如何使用threadlocal存储线程专有对象的详细内容。
舟山分类信息网,免费分类信息发布

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product