我想知道如何在快速取消响应性和性能之间达成妥协,我的线程的主体看起来类似于这个循环:
for(int i=0; i<HUGE_NUMBER; ++i) {
//some easy computation like adding numbers
//which are result of previous iteration of this loop
}如果循环体中的计算非常容易,那么在每个迭代中添加简单的检查反应:
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException("Cancelled");
}允许减慢代码的执行速度。
即使我将上述条件更改为:
if (i % 100 && Thread.currentThread().isInterrupted()) {
throw new InterruptedException("Cancelled");
}然后编译器不能仅在某些特定情况下预计算i的值和检查条件,因为HUGE_NUMBER是可变的,可以有不同的值。
因此,我想问一下,是否有任何智能方式()可以将这样的检查添加到所呈现的代码中,同时知道:
HUGE_NUMBER是可变的,可以有不同的值。我想说的是,循环的一次迭代是相当快的,但是迭代的HUGE_NUMBER可能需要更多的时间,这就是我想要避免的。
发布于 2013-11-24 21:38:11
首先,在这种情况下使用Thread.interrupted()而不是Thread.currentThread().isInterrupted()。
您应该考虑检查中断标志是否真的太慢您的计算!一方面,如果循环体非常简单,那么即使是大量的迭代(上限是Integer.MAX_VALUE)也会在几秒钟内运行。即使在检查中断标志会导致20 %或30%的开销时,这也不会给算法的整个运行时增加太多。
另一方面,如果循环体不是那么简单,运行时间也会更长,那么测试中断标志将不是一个显著的开销,我认为。
不要做像if (i % 10000 == 0)这样的把戏,因为这会比“短”Thread.interrupted()慢得多。
您可以使用一个小技巧--但是要三思,因为它会使您的代码变得更加复杂和可读性更低:
每当你有这样的循环时:
for (int i = 0; i < max; i++) {
// loop-body using i
}您可以将i的总范围划分为大小INTERVAL_SIZE的几个间隔。
int start = 0;
while (start < max) {
final int next = Math.min(start + INTERVAL_SIZE, max);
for(int i = start; i < next; i++) {
// loop-body using i
}
start = next;
}现在,您可以在内环之前或之后添加中断检查!
我使用下面的循环体在我的系统(JDK 7)上做了一些测试
if (i % 2 == 0) x++;和Integer.MAX_VALUE / 2迭代。结果如下(热身后):
因此,即使循环体像上面那样简单,每次迭代检查的开销也只有14%!因此,建议不要做任何技巧,但只需在每次迭代中通过检查中断标志!
发布于 2013-11-24 21:37:59
使您的计算成为Iterator。
虽然这听起来不太有用,但这里的好处是您可以很容易地编写过滤器迭代器,这些迭代器非常灵活。他们可以添加和删除简单-即使通过配置,如果你愿意。有很多好处--试试吧。
然后,您可以添加一个过滤Iterator,它定期监视时间并检查中断--甚至更灵活。
您甚至可以在不影响原始计算的情况下添加进一步的筛选,方法是将原始计算与脆性状态检查相加。
https://stackoverflow.com/questions/20181097
复制相似问题