具有超时的Java调用方法

时间:2016-06-09 20:52:50

标签: java multithreading timeout

我有一个程序使用状态空间搜索算法(A *,IDA *等)来解决一些问题。我想运行~30-50次测试迭代来获取一些信息(平均运行时间,扩展节点等),但我的问题是,有时这些算法可能需要很长时间才能解决问题。我想选择在方法调用上设置超时以限制执行时间(所以我可以在一夜之间运行测试并让它们可靠地完成)。

假设Solvers(实现算法的类)按原样提供,不能更改。通过调用solve方法来使用它们,该方法返回List<Integer>

这是我目前正在使用的代码的相关部分,由stackoverflow上的类似线程提供:

int nTests = 50;
long timeout = 120;
double[] expandedAvg = new double[solvers.size()];        // averages of expanded nodes for each solver
int[] fails = new int[solvers.size()];        // number of timeouts for each solver

for (int i = 1; i <= nTests; i++) {
    int[][] problem = createProblem();         // creates a random solvable problem
    int j = 0;
    for (Solver solver : solvers) {
        boolean success = true;
        List<Integer> solution = null;

        if (timeout > 0) {
            Callable<List<Integer>> task = new Callable<List<Integer>>() {
                @Override
                public List<Integer> call() {
                    return solver.solve(problem);
                }
            };
            Future<List<Integer>> future = Executors.newCachedThreadPool().submit(task);
            try {
                solution = future.get(timeout, TimeUnit.SECONDS);
            }
            catch (TimeoutException e) {
                success = false;
                System.out.println("FAIL");
            }
            catch (InterruptedException ignore) {}
            catch (ExecutionException e) {
                e.printStackTrace();
            }
            finally {
                future.cancel(true);
            }
        }
        else solution = solver.solve(problem);

        if (success) {
            // update the average
            expandedAvg[j] = expandedAvg[j] + (solver.expanded - expandedAvg[j]) / (i - fails[j]);
        }
        else fails[j]++;

        j++;
    }
}

然而,最终发生的事情是,在第一次失败的求解尝试之后,所有进一步的尝试都失败了。问题似乎是future.cancel(true)实际上并没有停止求解器的执行(我猜测整个应用程序在外循环结束后没有终止的事实,这意味着某些东西仍然存在然后在另一个线程中运行,然后占用所有资源,并且连续的那些资源不会获得任何CPU时间(并因此失败)。如果重要的话,我是从Eclipse运行的。

有没有办法确保线程在超时后停止?或者是否有其他方法可以实现我应该使用的超时?

0 个答案:

没有答案