【问题标题】:java: maximum execution time within for-loopjava:for循环内的最大执行时间
【发布时间】:2017-03-29 18:38:28
【问题描述】:

我有以下代码:

    List<String> instances2 = Arrays.asList("instances/umps20.txt","instances/umps22.txt","instances/umps24.txt","instances/umps26.txt","instances/umps28.txt","instances/umps30.txt","instances/umps32.txt");
    List<Integer> qq1 = Arrays.asList(9,10,11,12,13,14,14);
    List<Integer> qq2 = Arrays.asList(4,4,5,5,5,5,6);

    for (int i = 0; i<7; i++) {
        Tournament t = p.process(instances2.get(i));    
        int nTeams = t.getNTeams();
        int q1 = qq1.get(i);
        int q2 = qq2.get(i);
        UndirectedGraph graph = g.create(t, q1, q2);
        new Choco(graph, nTeams);
        }
    }

现在我想对每次迭代设置一个限制。因此,假设 3h = 10 800 000 毫秒后,我希望 for 循环中的所有内容都停止并开始循环的下一次迭代。有什么想法吗?

提前致谢!

尼古拉斯

【问题讨论】:

  • 您是想限制执行时间以防万一,还是只是对当时的计算结果感兴趣?
  • 如果我的算法在那之后还没有找到解决方案,那么它是不可行的,所以它应该继续下一个问题。 New Choco(...) 尝试为给定的图形找到图形着色(使用约束编程),但如果花费的时间超过 3 小时,它应该继续。

标签: java timer limit


【解决方案1】:

您可以在开始循环之前获取系统时间,并在每次迭代后进行比较,以检查时间是否超过指定时间,如下所示:

在for循环开始时:

long start = System.currentTimeMillis();

在每次迭代中:

if(start + 10_800_000 >= System.currentTimeMillis()){
    start = System.currentTimeMillis();
    i++;
}

你必须删除 for 循环中的 i++

for (int i = 0; i<7;) {

【讨论】:

  • 您好,感谢您的帮助,但是如果在新的 choco(...) 行之后添加 if(...) 它将首先尝试完成新的 choco(...) 行在到达 if(...) 之前它不起作用,还是我错了?
  • 他正在寻找一种方法,在 x 次之后通过循环中断当前迭代的执行。您的方法仅在每次迭代后检查时间是否已过,它在迭代时永远不会中断。
  • 是的,这正是我想要的。
【解决方案2】:

您必须创建一个新线程来运行您的循环,ExecutorService 将在指定的时间内运行此循环(或您放入 call() 方法的任何代码)。

这里是一个任务的演示,需要 5 秒运行,3 秒后会被中断:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class QuickTest {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> future = executor.submit(new Task());

        try {
            System.out.println("Started..");    // your task is running
            System.out.println(future.get(3, TimeUnit.SECONDS));    // enter the amount of time you want to allow your code to run
            System.out.println("Finished!");    // the task finished within the given time
        } catch (TimeoutException e) {
            future.cancel(true);
            System.out.println("Terminated!");  // the task took too long and was interrupted
        }

        executor.shutdownNow();
    }
}

class Task implements Callable<String> {    
    @Override
    public String call() throws Exception {  // enter the code you want to run for x time in here
        Thread.sleep(5000); // Just to demo some code which takes 5 seconds to finish.
        return "Ready!";    // code finished and was not interrupted (you gave it enough time).
    }
}

【讨论】:

    【解决方案3】:

    有很多方法可以实现所请求的功能。

    一种方法可能是将for 中的代码转换为FutureTask 对象并将其提交给ExecutorService - 即使只有1 个线程,如果循环必须按顺序执行 - 例如

    ExecutorService executor = Executors.newFixedThreadPool(1);
    

    拥有FutureTask(或任何其他实现Future 接口的对象)的好处是,cancel() 方法可用于确保中断的迭代不会产生任何副作用。

    对于中断,有很多选择。例如,可以使用javax.swing.Timer 类,它会在计时器到期后触发ActionEvent 通知。

    在上述方法中,任务(for 循环代码)将一直执行直到完成,或者直到收到来自计时器的ActionEvent。在后一种情况下,可以使用对cancel() 的调用来停止正在运行的任务,并启动下一个任务。总迭代次数的计数器可以保持在同一个地方。

    对于更复杂的解决方案,可以使用ExecutorService 的各种实现和超时规范选项,就像在另一个StackOverflow question 中一样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-15
      • 2011-04-16
      • 2012-03-07
      相关资源
      最近更新 更多