当前位置: 首页 > news >正文

电子商务网站建设文档如何购买虚拟主机做网站

电子商务网站建设文档,如何购买虚拟主机做网站,网页资源下载,网络宣传渠道ThreadLocal基础概念:IT-BLOG-CN ThreadLocal是Java中用于在同一个线程中存储和隔离变量的一种机制。通常情况下,我们使用ThreadLocal来存储线程独有的变量,并在任务完成后通过remove方法清理这些变量,以防止内存泄漏。然而&…

ThreadLocal基础概念:IT-BLOG-CN

ThreadLocalJava中用于在同一个线程中存储和隔离变量的一种机制。通常情况下,我们使用ThreadLocal来存储线程独有的变量,并在任务完成后通过remove方法清理这些变量,以防止内存泄漏。然而,在使用线程池时,线程会被重用,这可能导致ThreadLocal变量未被及时清理,从而引发内存泄漏问题。

除了直接调用ThreadLocalremove方法外,还有一些其他方式可以帮助释放ThreadLocal变量:

一、在线程池中使用自定义的ThreadFactory

创建一个自定义的ThreadFactory,在创建线程时添加钩子,以便在任务完成后清理ThreadLocal变量。扩展:搭建统一线程池平台,对该部分进行了改造。提供多个工厂,就包含自动清理工厂。

import java.util.concurrent.ThreadFactory;public class CleaningThreadFactory implements ThreadFactory {private final ThreadFactory defaultFactory = Executors.defaultThreadFactory();@Overridepublic Thread newThread(Runnable r) {return defaultFactory.newThread(() -> {try {r.run();} finally {// 清理ThreadLocal变量ThreadLocalHolder.clear();}});}
}

这里的ThreadLocalHolder就是所有ThreadLocal的一个管理类,这里举个例子:

public class ThreadLocalHolder {
private static final ThreadLocal<AggAlibabaRerQueryResponse> TL_AGG_REF_RER = new ThreadLocal<>();
private static final ThreadLocal<OpenAlibabaSearchResponse> TL_ORDER_DETAIL = new ThreadLocal<>();// get/set 只流一个参考
public static void setAggRefRer(AggAlibabaRerQueryResponse aggRefRer) {
TL_AGG_REF_RER.set(aggRefRer);
}public static FlightRefRerQueryResponse getFlightRefRer() {return TL_FLIGHT_REF_RER.get();
}/*** 用于清空threadlocal,否则会有内存泄漏*/public static void clear() {TL_AGG_REF_RER.remove();TL_ORDER_DETAIL.remove();
}

二、使用ThreadPoolExecutor的钩子方法

可以扩展ThreadPoolExecutor并覆盖其beforeExecuteafterExecute方法,以便在任务执行前后进行清理操作。

import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.LinkedBlockingQueue;public class CleaningThreadPoolExecutor extends ThreadPoolExecutor {public CleaningThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, LinkedBlockingQueue<Runnable> workQueue) {super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);}@Overrideprotected void beforeExecute(Thread t, Runnable r) {super.beforeExecute(t, r);// 清理之前的ThreadLocal变量ThreadLocalHolder.clear();}@Overrideprotected void afterExecute(Runnable r, Throwable t) {super.afterExecute(r, t);// 清理当前的ThreadLocal变量ThreadLocalHolder.clear();}
}

三、使用装饰器模式包装RunnableCallable

可以创建一个装饰器,包装RunnableCallable任务,在任务执行前后进行清理操作。

import java.util.concurrent.Callable;public class CleaningRunnable implements Runnable {private final Runnable task;public CleaningRunnable(Runnable task) {this.task = task;}@Overridepublic void run() {try {task.run();} finally {// 清理ThreadLocal变量ThreadLocalHolder.clear();}}
}public class CleaningCallable<V> implements Callable<V> {private final Callable<V> task;public CleaningCallable(Callable<V> task) {this.task = task;}@Overridepublic V call() throws Exception {try {return task.call();} finally {// 清理ThreadLocal变量ThreadLocalHolder.clear();}}
}

四、使用ThreadLocal的子类

可以创建一个ThreadLocal的子类,并在任务完成后自动清理变量。可以通过覆盖initialValue方法来实现:finalize 出发的时机是在gc的时候,但是finalize方法在现代Java开发中并不推荐使用,因为它的执行时间和执行顺序是不确定的。

public class AutoCleanupThreadLocal<T> extends ThreadLocal<T> {@Overrideprotected void finalize() throws Throwable {this.remove();super.finalize();}
}

五、TheadLocal 实际使用案例

将整个流程中需要用到的接口数据都存储起来,这个流程中调用链路比较深,同时也存在并发的操作,可以使用ThreadLocal

public class ThreadLocalHolder {
private static final ThreadLocal<AggAlibabaRerQueryResponse> TL_AGG_REF_RER = new ThreadLocal<>();
private static final ThreadLocal<OpenAlibabaSearchResponse> TL_ORDER_DETAIL = new ThreadLocal<>();
private static final ThreadLocal<FlightAlibabaResponse> TL_FLIGHT_REF_RER = new ThreadLocal<>();
private static final ThreadLocal<XOrderAlibabaInfo> TL_X_ORDER_DETAIL = new ThreadLocal<>();
private static final ThreadLocal<FlightAlibabaResponseBodyType> TL_DOM_FLIGHT_SEARCH_RESULT = new ThreadLocal<>();
private static final ThreadLocal<ResponseAlibabaType> TL_RESCHEDULE_FLIGHT_SEARCH_RESULT = new ThreadLocal<>();// get/set 只流一个参考
public static void setAggRefRer(AggAlibabaRerQueryResponse aggRefRer) {
TL_AGG_REF_RER.set(aggRefRer);
}public static FlightRefRerQueryResponse getFlightRefRer() {return TL_FLIGHT_REF_RER.get();
}/*** 用于清空threadlocal,否则会有内存泄漏*/public static void clear() {TL_AGG_REF_RER.remove();TL_ORDER_DETAIL.remove();TL_FLIGHT_REF_RER.remove();TL_X_ORDER_DETAIL.remove();TL_DOM_FLIGHT_SEARCH_RESULT.remove();TL_RESCHEDULE_FLIGHT_SEARCH_RESULT.remove();
}

六、基础支持补充 ----- ThreadLocal 的实现原理

下面是ThreadLocal的类图结构,从图中可知:Thread类中有两个变量threadLocalsinheritableThreadLocals,二者都是ThreadLocal内部类ThreadLocalMap类型的变量,我们通过查看内部类ThreadLocalMap可以发现实际上它类似于一个HashMap。在默认情况下,每个线程中的这两个变量都为null

ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

只有当线程第一次调用ThreadLocalset或者get方法的时候才会创建他们(后面我们会查看这两个方法的源码)。除此之外,每个线程的本地变量不是存放在ThreadLocal实例中,而是放在调用线程的ThreadLocals变量里面(前面也说过,该变量是Thread类的变量)。也就是说,ThreadLocal类型的本地变量是存放在具体的线程空间上,相当于一个装载本地变量的工具壳,通过set方法将value添加到调用线程的threadLocals中,当调用线程调用get方法时候能够从它的threadLocals中取出变量。如果调用线程一直不终止,那么这个本地变量将会一直存放在他的threadLocals中,所以不使用本地变量的时候需要调用remove方法将threadLocals中删除不用的本地变量。下面我们通过查看ThreadLocalsetget以及remove方法来查看ThreadLocal具体实怎样工作的。

【1】set方法源码

public void set(T value) {//(1)获取当前线程(调用者线程)Thread t = Thread.currentThread();//(2)以当前线程作为key值,去查找对应的线程变量,找到对应的mapThreadLocalMap map = getMap(t);//(3)如果map不为null,就直接添加本地变量,key为当前线程,值为添加的本地变量值if (map != null)map.set(this, value);//(4)如果map为null,说明首次添加,需要首先创建出对应的mapelsecreateMap(t, value);
}

在上面的代码中,(2)处调用getMap方法获得当前线程对应的threadLocals(参照上面的图示和文字说明),该方法代码如下:

ThreadLocalMap getMap(Thread t) {return t.threadLocals; //获取线程自己的变量threadLocals,并绑定到当前调用线程的成员变量threadLocals上
}

如果调用getMap方法返回值不为null,就直接将value值设置到threadLocals中(key为当前线程引用,值为本地变量);如果getMap方法返回null说明是第一次调用set方法(前面说到过,threadLocals默认值为null,只有调用set方法的时候才会创建map),这个时候就需要调用createMap方法创建 threadLocals,该方法如下所示:createMap方法不仅创建了threadLocals,同时也将要添加的本地变量值添加到了threadLocals中。

void createMap(Thread t, T firstValue) {t.threadLocals = new ThreadLocalMap(this, firstValue);
}

【2】get方法源码:get方法的实现中,首先获取当前调用者线程,如果当前线程的threadLocals不为null,就直接返回当前线程绑定的本地变量值,否则执行setInitialValue方法初始化threadLocals变量。在setInitialValue方法中,类似于set方法的实现,都是判断当前线程的threadLocals变量是否为null,是则添加本地变量(这个时候由于是初始化,所以添加的值为null),否则创建threadLocals变量,同样添加的值为null

public T get() {//(1)获取当前线程Thread t = Thread.currentThread();//(2)获取当前线程的threadLocals变量ThreadLocalMap map = getMap(t);//(3)如果threadLocals变量不为null,就可以在map中查找到本地变量的值if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}//(4)执行到此处,threadLocals为null,调用该更改初始化当前线程的threadLocals变量return setInitialValue();
}private T setInitialValue() {//protected T initialValue() {return null;}T value = initialValue();//获取当前线程Thread t = Thread.currentThread();//以当前线程作为key值,去查找对应的线程变量,找到对应的mapThreadLocalMap map = getMap(t);//如果map不为null,就直接添加本地变量,key为当前线程,值为添加的本地变量值if (map != null)map.set(this, value);//如果map为null,说明首次添加,需要首先创建出对应的mapelsecreateMap(t, value);return value;
}

【3】remove方法的实现: remove方法判断当前线程对应的threadLocals变量是否为null,不为null就直接删除当前线程中指定的threadLocals变量。

public void remove() {//获取当前线程绑定的threadLocalsThreadLocalMap m = getMap(Thread.currentThread());//如果map不为null,就移除当前线程中指定ThreadLocal实例的本地变量if (m != null)m.remove(this);
}private void remove(ThreadLocal<?> key) {Entry[] tab = table;int len = tab.length;int i = key.threadLocalHashCode & (len-1);for (Entry e = tab[i];e != null;e = tab[i = nextIndex(i, len)]) {if (e.refersTo(key)) {e.clear();expungeStaleEntry(i);return;}}
}

【4】如下图所示: 每个线程内部有一个名为threadLocals的成员变量,该变量的类型为ThreadLocal.ThreadLocalMap类型(类似于一个HashMap),其中的key为当前定义的ThreadLocal变量的this引用,value为我们使用set方法设置的值。每个线程的本地变量存放在自己的本地内存变量threadLocals中,如果当前线程一直不消亡,那么这些本地变量就会一直存在(可能会导致内存溢出),因此使用完毕需要将其remove掉。

http://www.yayakq.cn/news/500898/

相关文章:

  • 详细的网站规划建设方案服务器长沙商城网站建设报价公示
  • 餐饮美食网站源码网站展示模板免费下载
  • 四川建设厅证网站是网站建设开票税率
  • 网站效果检测wordpress外网ip访问
  • 沈阳企业网站制作哪家好宜昌建设网站公司
  • 东莞网站推广方式太原企业网站制作
  • 自适应网站设计稿icp备案流程
  • 给素材网站做素材方法宁波品牌网站推广优化公司
  • 珠宝企业的门户网站开发天津室内设计学校
  • 网站制作建设有哪些东莞ppt免费模板下载网站
  • 建设企业网站登录901中国制造网外贸平台怎么注册
  • 电子商城网站建设费用全国企业信息管理系统
  • 如何作做网站logo在线设计生成器小智
  • 培训班在哪个网站找如何用vs的c 做网站
  • 网站开发需要的技术人员有什么福田欧曼重卡
  • 网站优化基础网站制作论文范文
  • 做店铺图片什么网站wordpress知更鸟配置
  • 网站建设策划表江门学做网站课程
  • 秦皇岛手机网站制作做大数据和网站开发的前景
  • php做的网站用什么后台哈尔滨 网站建设
  • 网站开发课程设计报告wordpress文章分类插件
  • 苏州有做网站的公司吗微信小程序开发框架
  • 海口网站建设q479185700棒wordpress插件查看
  • 做网站要的带宽是什么个人网站规划书模板
  • 哪些网站可以做花店推广wordpress收费注册
  • 做动态图片下载哪个网站好wordpress themes
  • 为公益组织做网站深圳视频seo
  • 如何做网站营销红杉树装修公司
  • 哪个网站可以做纸箱什么是网络营销啊
  • wix做网站流程Wordpress获取自定义分类