Java 如何让一个线程运行特定的时间,然后优雅的终止?

发布于 2022-09-01 05:53:15 字数 388 浏览 11 评论 0

有一个对象列表,按对象的过期时间戳升序排序,当内存快要不足时,想触发一个线程从头遍历列表,把列表前面过期的对象都释放掉(对象的资源是被pool的,必须手动release)

列表不是线程安全的(因为程序其他部分逻辑的原因,这里使用线程安全的集合类并不能解决问题),工作线程和释放资源的线程同时只能有一个操作对象列表

我的想法是,如果释放资源的线程在列表上操作太长时间,工作线程一直被阻塞,很长时间整个系统就不能提供服务了,所以我想限制每次释放资源的线程的执行时间,在给定的时间里能释放多少对象就释放多少(并且时间结束时,是优雅的结束释放工作),然后工作线程继续执行

请问如何实现我这个思路?如果同时只有一个线程访问对象列表,是不是把释放对象的工作放在工作线程中更好?怎么实现执行特定的时间呢?希望能有更标准的思路

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夏夜暖风 2022-09-08 05:53:15

工作线程和释放资源的线程同时只能有一个操作对象列表

这个前提决定了你必须使用synchronized块对操作这个列表的逻辑做保护,这个没得说;
剩下的问题就是:如何让回收线程操作列表的时间更短?

我的思路是这样的:很简单,你的回收线程在操作列表时,只做一件事情:把该回收的对象移出列表,放到另一个地方去(比如另一个列表,"列表2")

仅仅是“移出”的话,这个操作是非常快的,不知道你这个列表有多大,一般情况都能瞬间完成;

然后让工作线程去操作列表,回收线程慢慢来处理"列表2"中的回收工作, 互不干扰;

如果你的对象列表确实很极端地大,那么你可以将回收线程设计成"主-次"线程2层结构,其中主线程开启子线程对列表做移出操作,并持有子线程对象的应用;
而子线程,实现了interrupt方法,在方法中抛出一个你自定义的exception;

主线程在启动子线程后,sleep(你认为合适的时间),醒来时若发现子线程还未结束,就调用子线程的interrupt方法

浪漫之都 2022-09-08 05:53:15

我觉得楼上几位说的很对,释放是个轻量操作。如果你实在纠结阻塞时间我有个思路。
因为你的对象列表(假设叫ol)不是线程安全的,所以每次操作都会锁住ol。
那可以单开一个守护线程轮询jvm内存,一旦内存到达这个阀值就可以认为快用光了,然后将一个全局变了标记为true。
当你的工作线程发现这个全局变量为true后,在保存新对象到ol前,将ol最前面的几个对象(1个或2个,不用多因为在轮询线程没发现内存回复前其他工作线程仍会释放)释放,然后保存新的。
那个轮询内存的守护线程发现内存低于指定的阀值后在将全局变量设为false,这样新的工作线程不会在有释放操作。
这样的话你完全没有引入任何需要锁ol的线程,你ol的阻塞率还是你原来的工作线程。由于轮询内存线程是守护线程你也不用操心优雅的终止问题。

更新

突然发现你问的是如果让线程运行指定的时间。。。。
线程卡在while前记一下开始时间,你循环里根据开始时间计算耗时,达到你指定的时候跳出或sleep都行。

老街孤人 2022-09-08 05:53:15

如果单纯的释放的话,应该不会是多么耗时的操作,再说啦jvm垃圾回收的时候都有stop the world的时候,你这个逻辑有堵塞的情况出现,也是必然的。如果你的数量的确是巨大的 那么你可以控制每次回收的个数,让堵塞的时间尽可能小。再有就是在程序上限制对象池的个数,因为你不限制的,即使再优的算法,对象数目一多,程序也极容易失控。

我恋#小黄人 2022-09-08 05:53:15

如果释放操作是非常轻量级的操作,就是释放每个对象的时间都极短,可以在释放线程中写个循环判断当前执行时间一个一个的释放,类似这样:

codepublic void run() {
    while(在给定的时间) {
        release(object);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文