如何让线程超时支持超时

两个问题:.net如何让线程超时支持超时.net如何让线程超时在执行结束后销毁?本文就解决这二个问题

线程超时执行完、遇到未处理异常和被终止后就自动不可用了如果是垃圾,自然会被 GC 给回收有一点需要说明的是:线程超时的未处理异常会导致应用程序的终止,一个线程超时的异常不会自动冒泡到其它線程超时

开发人员经常会遇到这样的方法調用场景:调用一个方法时等待一段时间(一般来说是给定一个时间段)如果该方法能够在给定的时间段之内得到结果,那么将结果立刻返回反之,超时返回默认结果等待/通知的经典范式,即加锁、条件循环和处理逻辑3个步骤而这种范式无法做到超时等待。而超时等待的加入只需要对经典范式做出非常小的改动,改动内容如下所示假设超时时间段是T,那么可以推断出在当前时间now+T之后就会超时定義如下变量

等待超时模式就是在等待/通知范式基础上增加了超时控制,这使得该模式相比原有范式更具有灵活性因为即使方法执行时間过长,也不会“永久”阻塞调用者而是会按照调用者的要求“按时”返回。

数据库连接池的设计也可以复用到其他的资源获取的场景针对昂贵资源(比如数据库连接)的获取都应该加以超时限制。

对于服务端的程序经常面对的是客户端传入的短小(执行时间短、工莋内容较为单一)任务,需要服务端快速处理并返回结果如果服务端每次接受到一个任务,创建一个线程超时然后进行执行,这在原型阶段是个不错的选择但是面对成千上万的任务递交进服务器时,如果还是采用一个任务一个线程超时的方式那么将会创建数以万记嘚线程超时,这不是一个好的选择因为这会使操作系统频繁的进行线程超时上下文切换,无故增加系统的负载而线程超时的创建和消亡都是需要耗费系统资源的,也无疑浪费了系统资源

线程超时池技术能够很好地解决这个问题,它预先创建了若干数量的线程超时并苴不能由用户直接对线程超时的创建进行控制,在这个前提下重复使用固定或较为固定数目的线程超时来完成任务的执行这样做的好处昰,一方面消除了频繁创建和消亡线程超时的系统资源开销,另一方面面对过量任务的提交能够平缓的劣化。

线程超时池的本质就是使用了一个线程超时安全的工作队列连接工作者线程超时和客户端线程超时客户端线程超时将任务放入工作队列后便返回,而工作者线程超时则不断地从工作队列上取出工作并执行当工作队列为空时,所有的工作者线程超时均等待在工作队列上当有客户端提交了一个任务之后会通知任意一个工作者线程超时,随着大量的任务被提交更多的工作者线程超时会被唤醒。

线程超时池中线程超时数量并不是樾多越好具体的数量需要评估每个任务的处理时间,以及当前计算机的处理器能力和数量使用的线程超时过少,无法发挥处理器的性能;使用的线程超时过多将会增加系统的无故开销,起到相反的作用

之前在实现熔断降级组件时需偠实现一个接口的超时中断,意思是业务在使用熔断降级功能时,在平台上设置了一个超时时间如果在请求进入熔断器开始计时,并苴接口在超时时间内没有响应则需要提早中断该请求并返回。

比如正常下游接口的超时时间为800ms但是因为自身业务的特殊需求,最多只能等200ms如果200ms之内没有数据返回,则返回降级数据这里处理请求的线程超时可以看成是tomcat线程超时池中的一个线程超时,如果通过线程超时池返回的Future可以很轻松的实现超时返回,但是这种情况下并不能拿到Futrue,需要换一种思路

中断一个线程超时的思路有哪些?
除了已经废棄的Thread.stop, Thread.suspend, Thread.resume 方法剩下的貌似只有一种方案了,就是调用当前线程超时的interrupt()但是这个方法的作用并不是中断线程超时,而是设置一个标识通知該线程超时可以被中断了,到底是继续执行还是中断返回,由线程超时本身自己决定

具体来说,当对一个线程超时调用了interrupt()之后如果該线程超时处于被阻塞状态(比如执行了wait、sleep或join等方法),那么会立即退出阻塞状态并抛出一个InterruptedException异常,在代码中catch这个异常进行后续处理洳果线程超时一直处于运行状态,那么只会把该线程超时的中断标志设置为 true仅此而已,所以interrupt()并不能真正的中断线程超时不过在rpc调用的場景中,请求线程超时一般都处于阻塞状态等待数据返回,这时interrupt()方法是可以派上用场的

那么,要实现指定超时时间内中断请求线程超時还有最后一个问题需要解决:什么时候,由谁去执行interrupt()方法

必然这个方法只能由其它线程超时来执行了(自己都阻塞了,执行个鬼)而且是在请求进入熔断器时,并在超时时间之后执行有点绕,比如超时时间是200ms那么请求进入熔断器之后,再过200ms就执行interrupt(),但是在200ms之內有数据返回那么就不执行interrupt()了。

需求已经很明确了相当于延迟执行一个task,其内部逻辑就是执行请求线程超时的interrupt()当然还有其它的逻辑。



在请求进入熔断器时顺便提交一个任务到线程超时池中等待执行,如果接口在超时时间内没有返回那么该任务会被触发,并执行请求线程超时的interrupt方法这样就实现了请求线程超时的中断(因为这时请求线程超时正在被阻塞,等待数据返回)另外需要清空定时任务,鈈然这个任务会一直执行

如果接口正常返回了,也要记得清空定时任务并且在请求退出熔断器的时候,记得恢复请求线程超时的中断標识如何恢复?在请求线程超时中执行下面代码即可


// 参数为true,可以清除中断标识

执行当前线程超时(即请求线程超时)的isInterrupted方法

使用這种方式实现请求的超时中断,在QPS很高的情况下会有额外的性能损失,因为每次请求都要提交一个任务到线程超时池中等待执行

如果伱现在在JAVA这条路上挣扎,也想在IT行业拿高薪可以参加我们的训练营课程,选择最适合自己的课程学习技术大牛亲授,7个月后进入名企拿高薪。我们的课程内容有:Java工程化、高性能及分布式、高性能、深入浅出高架构。性能调优、SpringMyBatis,Netty源码分析和大数据等多个知识点如果你想拿高薪的,想学习的想就业前景好的,想跟别人竞争能取得优势的想进阿里面试但担心面试不过的,你都可以来q群号为:

1、具有1-5工作经验的,面对目前流行的技术不知从何下手需要突破技术瓶颈的可以加。

2、在公司待久了过得很安逸,但跳槽时面试碰壁需要在短时间内进修、跳槽拿高薪的可以加。

3、如果没有工作经验但基础非常扎实,对java工作机制常用设计思想,常用java开发框架掌握熟练的可以加。

4、觉得自己很牛B一般需求都能搞定。但是所学的知识点没有系统化很难在技术领域继续突破的可以加。

5.阿里Java高级夶牛直播讲解知识点分享知识,多年工作经验的梳理和总结带着大家全面、科学地建立自己的技术体系和技术认知!

我要回帖

更多关于 线程超时 的文章

 

随机推荐