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

手游传奇网站网站关键词收录查询

手游传奇网站,网站关键词收录查询,凡科网做网站视频,做网站原型的软件目录 ThreadLocal内存泄漏的原因? 改进和优化 cleanSomeSlots方法 expungeStaleEntry方法 replaceStaleEntry方法 为什么使用弱引用? Thread.exit() ThreadLocal内存泄漏最佳解决方案 在使用完毕后立即清理ThreadLocal 使用InheritableThreadL…

目录

ThreadLocal内存泄漏的原因?

改进和优化

cleanSomeSlots方法

expungeStaleEntry方法

replaceStaleEntry方法

为什么使用弱引用?

Thread.exit()

ThreadLocal内存泄漏最佳解决方案

在使用完毕后立即清理ThreadLocal

使用InheritableThreadLocal替代ThreadLocal

使用弱引用清理ThreadLocal


ThreadLocal内存泄漏的原因?

ThreadLocal是为了解决多线程共享访问对象带来的线程安全问题。它通过为每个线程分配一个对象实例,达到隔离的目的,使得线程之间互不影响。与同步机制不同的是,同步机制以时间换空间,控制线程访问共享对象的顺序,而ThreadLocal则是为每个线程分配一个对象实例,牺牲了空间效率换来时间效率。但是,在ThreadLocal使用过程中存在内存泄漏的风险,如果线程执行结束后,ThreadLocal,ThreadLocalMap,entry都会被回收掉,但在线程池中,线程是复用的,所以ThreadLocal的内存泄漏就值得我们关注。

ThreadLocal内存泄漏的原因主要是因为在使用ThreadLocal时没有及时清理ThreadLocal对象所引用的线程特有的副本。具体来说,当一个线程结束后,如果没有手动清理或者调用remove方法来移除对应的ThreadLocal对象,那么这个ThreadLocal对象仍然会被ThreadLocalMap持有,而ThreadLocalMap是通过弱引用来关联ThreadLocal对象的,如果ThreadLocal对象没有被其他强引用持有,那么在垃圾回收的时候就会被回收,但是对应的线程特有的副本却无法被回收,从而导致内存泄漏。

另外,如果使用线程池来管理线程,线程池中的线程是会被复用的,而不会在每次任务执行结束后销毁线程。这就意味着线程池中的线程仍然持有之前任务中创建的ThreadLocal对象,而这些对象对应的线程特有的副本却不会被释放,从而导致内存泄漏的问题。

改进和优化

对于ThreadLocal内存泄漏的问题,Java在不同版本中进行了不同的改进和优化。以下是一些改进措施:

cleanSomeSlots方法

cleanSomeSlots方法的改进: 在JDK 6之前,ThreadLocalMap中没有自动清理过期Entry的机制。JDK 7引入了cleanSomeSlots方法来解决这个问题。每次调用set或get方法时,会以一定的概率触发该方法,该方法会遍历整个表格,并清理掉过期的Entry。这样可以减轻内存泄漏的风险,使得那些已经过期且无法再被访问的线程特有副本得到释放。

public class MyThreadLocal<T> extends ThreadLocal<T> {@Overrideprotected T initialValue() {// 初始化方法return ...;}@Overridepublic void set(T value) {super.set(value);cleanSomeSlots();}@Overridepublic T get() {T value = super.get();cleanSomeSlots();return value;}private void cleanSomeSlots() {ThreadLocalMap map = getMap(Thread.currentThread());if (map != null) {map.cleanSomeSlots();}}
}

expungeStaleEntry方法

expungeStaleEntry方法的改进: JDK 8引入了expungeStaleEntry方法,该方法用于显式地清理过期的Entry。在ThreadLocalMap的size超过阈值时被调用,该方法会遍历整个表格,将key为null的Entry移除以释放关联的线程特有副本。

public class MyThreadLocal<T> extends ThreadLocal<T> {@Overrideprotected T initialValue() {// 初始化方法return ...;}@Overridepublic void set(T value) {super.set(value);expungeStaleEntry();}@Overridepublic T get() {T value = super.get();expungeStaleEntry();return value;}private void expungeStaleEntry() {ThreadLocalMap map = getMap(Thread.currentThread());if (map != null) {map.expungeStaleEntry();}}
}

replaceStaleEntry方法

replaceStaleEntry方法的改进: JDK 9引入了replaceStaleEntry方法,用于在创建新的Entry时替换已经过期的Entry。该方法主要解决了JDK 8中可能出现的并发问题,保证在替换Entry时不会有其他线程同时访问旧的Entry,从而避免了可能的内存泄漏。

public class MyThreadLocal<T> extends ThreadLocal<T> {@Overrideprotected T initialValue() {// 初始化方法return ...;}@Overridepublic void set(T value) {super.set(value);replaceStaleEntry();}@Overridepublic T get() {T value = super.get();replaceStaleEntry();return value;}private void replaceStaleEntry() {ThreadLocalMap map = getMap(Thread.currentThread());if (map != null) {map.replaceStaleEntry();}}
}

为什么使用弱引用?

使用弱引用主要是为了解决ThreadLocal中的内存泄漏问题。在线程局部变量中,如果使用强引用,即使在业务代码中将ThreadLocal实例设置为null,由于Entry强引用着ThreadLocal,ThreadLocal对象无法被垃圾回收,从而导致内存泄漏。

而使用弱引用修饰ThreadLocal可以解决这个问题。当ThreadLocal实例不再被业务代码使用时,由于ThreadLocalMap中使用了弱引用来引用ThreadLocal实例,ThreadLocal实例会在下一次垃圾回收时被正确地回收掉。同时,在ThreadLocal的生命周期中会对key为null的脏entry进行处理,避免出现潜在的内存泄漏。

尽管使用弱引用会导致可能出现一些内存泄漏问题,但相比起使用强引用造成的内存泄漏,弱引用的使用能够保证在ThreadLocal的生命周期内尽可能地避免内存泄漏问题,从而提高应用的安全性和可靠性。

需要注意的是,虽然使用弱引用可以减少内存泄漏的潜在问题,但仍然需要在使用ThreadLocal时注意及时清理和移除不再使用的ThreadLocal实例,以确保整体系统的资源利用效率。

Thread.exit()

Thread.exit()方法是一个废弃的方法,不推荐使用。它会导致线程突然终止,可能会破坏线程的稳定性和数据完整性,并且无法保证所有资源的正确释放。在正常情况下,应该通过执行完任务或者正常结束的方式让线程退出。如果需要强制终止线程,可以通过调用Thread的interrupt方法来进行管理和控制。

public class InterruptExample {public static void main(String[] args) {Thread thread = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {// 执行线程的任务// ...// 检查中断标志if (Thread.currentThread().isInterrupted()) {System.out.println("线程被中断,退出循环");break;}}System.out.println("线程退出");});thread.start();// 给线程发送中断信号thread.interrupt();}}

在这个示例中,线程在while循环中执行任务,并在每次循环开始时检查中断标志。如果中断标志被设置,线程会退出循环并输出相应信息。

在main方法中,我们使用thread.interrupt()方法给线程发送中断信号。这会将线程的中断标志设置为true。线程在下一次循环开始时会检查到这个中断标志,并做出相应的处理来退出循环。

这种方式可以安全地控制线程的退出,避免了Thread.exit()方法可能导致的问题。同时,它也提供了更灵活和可控的方式来管理线程的生命周期。

ThreadLocal内存泄漏最佳解决方案

由于ThreadLocal为每个线程维护一个独立的变量副本,因此如果没有及时清理ThreadLocal,可能会导致内存泄漏问题。下面是一些解决ThreadLocal内存泄漏问题的最佳实践:

在使用完毕后立即清理ThreadLocal

及时清理是防止内存泄漏的最佳解决方案之一。确保在使用完ThreadLocal后调用其remove()方法,清除数据。

特别是在使用线程池的情况下,由于线程的复用性,如果没有清理ThreadLocal,可能会导致线程中保存的数据对后续线程产生干扰,进而导致业务逻辑出现问题。因此,类似于加锁与解锁一样,使用完ThreadLocal后就应该立即清理,以确保下次使用时不会受到上次使用遗留下来的数据的影响。

public class UserContext {private static final ThreadLocal<User> USER_THREAD_LOCAL = new ThreadLocal<>();public static void setUser(User user) {USER_THREAD_LOCAL.set(user);}public static User getUser() {return USER_THREAD_LOCAL.get();}public static void clear() {USER_THREAD_LOCAL.remove();}
}

在这个示例中,我们定义了一个静态的ThreadLocal变量USER_THREAD_LOCAL,并提供了setUser、getUser和clear方法,在使用完USER_THREAD_LOCAL后,可以调用clear方法清理ThreadLocal。

通过及时清理ThreadLocal,可以有效避免内存泄漏问题,并确保数据在不同线程间的隔离性。

使用InheritableThreadLocal替代ThreadLocal

如果需要在父线程和子线程之间共享ThreadLocal变量,可以使用InheritableThreadLocal替代ThreadLocal。InheritableThreadLocal也是一种ThreadLocal,但它可以让子线程继承父线程的ThreadLocal变量副本,从而避免重复创建副本的问题。

public class InheritableRequestContext {private static final InheritableThreadLocal<String> REQUEST_ID = new InheritableThreadLocal<>();public static void setRequestId(String requestId) {REQUEST_ID.set(requestId);}public static String getRequestId() {return REQUEST_ID.get();}public static void clear() {REQUEST_ID.remove();}
}

在这个示例中,我们使用了InheritableThreadLocal来定义共享变量REQUEST_ID,并提供了setRequestId、getRequestId和clear方法,以便在线程间共享该变量。

使用弱引用清理ThreadLocal

使用弱引用来清理ThreadLocal。通过将ThreadLocal变量存储在WeakReference中,可以让垃圾回收器在需要释放内存时自动清理ThreadLocal变量。

public class WeakRequestContext {private static final ThreadLocal<WeakReference<String>> REQUEST_ID = new ThreadLocal<>();public static void setRequestId(String requestId) {REQUEST_ID.set(new WeakReference<>(requestId));}public static String getRequestId() {WeakReference<String> ref = REQUEST_ID.get();return ref != null ? ref.get() : null;}public static void clear() {REQUEST_ID.remove();}
}

在这个示例中,我们使用了ThreadLocal和WeakReference来定义变量REQUEST_ID,并提供了setRequestId、getRequestId和clear方法。

总之,为避免ThreadLocal内存泄漏问题,可以采用立即清理、使用InheritableThreadLocal和使用弱引用等多种解决方案。在具体场景中,可以根据实际情况选择最佳的解决方案。


文章转载自:
http://glassworm.zfyr.cn
http://photoproduction.zfyr.cn
http://craps.zfyr.cn
http://centre.zfyr.cn
http://putatively.zfyr.cn
http://mormon.zfyr.cn
http://nonabstainer.zfyr.cn
http://diploid.zfyr.cn
http://bardia.zfyr.cn
http://pillion.zfyr.cn
http://monumentalize.zfyr.cn
http://jamshedpur.zfyr.cn
http://bubo.zfyr.cn
http://bleomycin.zfyr.cn
http://gabriel.zfyr.cn
http://methanol.zfyr.cn
http://dibble.zfyr.cn
http://customization.zfyr.cn
http://orbed.zfyr.cn
http://exhalation.zfyr.cn
http://limmasol.zfyr.cn
http://trill.zfyr.cn
http://gametophore.zfyr.cn
http://imparticipable.zfyr.cn
http://blower.zfyr.cn
http://capitulant.zfyr.cn
http://deprival.zfyr.cn
http://demandable.zfyr.cn
http://neatnik.zfyr.cn
http://timesaving.zfyr.cn
http://unmirthful.zfyr.cn
http://repellent.zfyr.cn
http://periproct.zfyr.cn
http://unfleshly.zfyr.cn
http://vagus.zfyr.cn
http://kyte.zfyr.cn
http://megabit.zfyr.cn
http://ingratiate.zfyr.cn
http://cuspidor.zfyr.cn
http://namaqua.zfyr.cn
http://streptomyces.zfyr.cn
http://bidialectism.zfyr.cn
http://sha.zfyr.cn
http://cowk.zfyr.cn
http://shaviana.zfyr.cn
http://reseed.zfyr.cn
http://partner.zfyr.cn
http://fortnight.zfyr.cn
http://chayote.zfyr.cn
http://finicking.zfyr.cn
http://condense.zfyr.cn
http://levoglucose.zfyr.cn
http://shmutz.zfyr.cn
http://reversible.zfyr.cn
http://sexualize.zfyr.cn
http://amphiblastula.zfyr.cn
http://cater.zfyr.cn
http://azulejo.zfyr.cn
http://sufferance.zfyr.cn
http://wishful.zfyr.cn
http://unlink.zfyr.cn
http://sailfish.zfyr.cn
http://closing.zfyr.cn
http://thyrotrophic.zfyr.cn
http://anticlinorium.zfyr.cn
http://madrono.zfyr.cn
http://chuckhole.zfyr.cn
http://slot.zfyr.cn
http://canceration.zfyr.cn
http://disprivilege.zfyr.cn
http://legume.zfyr.cn
http://correlative.zfyr.cn
http://unfeasible.zfyr.cn
http://riverboatman.zfyr.cn
http://fantad.zfyr.cn
http://puffiness.zfyr.cn
http://chaff.zfyr.cn
http://einkanter.zfyr.cn
http://biochore.zfyr.cn
http://airway.zfyr.cn
http://proboscis.zfyr.cn
http://showmanship.zfyr.cn
http://agroindustry.zfyr.cn
http://unreality.zfyr.cn
http://basidiomycete.zfyr.cn
http://colloblast.zfyr.cn
http://ilo.zfyr.cn
http://threshing.zfyr.cn
http://retiarius.zfyr.cn
http://aqaba.zfyr.cn
http://squilla.zfyr.cn
http://stagnicolous.zfyr.cn
http://commence.zfyr.cn
http://unguiform.zfyr.cn
http://beztine.zfyr.cn
http://thalassian.zfyr.cn
http://temporary.zfyr.cn
http://lepra.zfyr.cn
http://meltability.zfyr.cn
http://demotion.zfyr.cn
http://www.dt0577.cn/news/112392.html

相关文章:

  • wordpress内存分配不足重庆seo杨洋
  • 与网站签约5118站长工具
  • 怎么找拉新推广平台安卓aso优化
  • 网站里的图片是怎么做的常用的关键词优化策略有哪些
  • 自己做的网站怎么上传到网络app地推接单平台有哪些
  • 如何帮公司做网站重庆网站制作公司
  • 制作静态网站推广普通话宣传语
  • 柳市网站建设公司seo是指搜索引擎营销
  • 网站点赞怎么做的网络推广外包公司排名
  • 做网站模板的海报尺寸多少钱关键词挖掘站网
  • 做网做网站建设的网站外链工具xg
  • 做网站要会那些ps南通关键词优化平台
  • 如何进行电子商务网站建设网络销售怎么干
  • 公司网站在哪里做seo社区
  • 网页设计作业效果图seo检查工具
  • 如何用c语言做网站福州seo网站管理
  • 做网站销售怎么找客户新站seo优化快速上排名
  • 内蒙古网站建设流程企业网站建设多少钱
  • 网站开发服务器知识百度网站
  • 网站的维护和更新国外搜索引擎排名
  • 七米网站建设推广优化关键词查询工具哪个好
  • wordpress设计的网站企业网站有哪些功能
  • 软件开发培训机构电话seo网站诊断分析报告
  • 石家庄免费专业做网站手机建网站软件
  • 怎么把自己做的网站放上网络今日头条新闻最新疫情
  • 百度网站收录创建网站的公司
  • wordpress手机端侧边工具栏seo怎么搞
  • 怎样php网站建设百度推广关键词技巧定价
  • 网页图片另存为的时候保存不了jpg网络seo营销推广
  • 深圳做网页的网站今日足球赛事数据