2

I've got the folowing code:

    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);
        }
    }

Now i want to put a limit on each iteration. So after let's say 3h = 10 800 000ms, i would like for everything in the for-loop to stop and start the next iteration over the loop. Any ideas?

Thanks in advance!

Nicholas

  • 1
    Are you trying to limit the execution time as a precaution, or are you just interested in the results of the computation up to that point? – Horst Mar 29 '17 at 18:45
  • If my algorithm hasn't found a solution after that time, it isn't feasible so it should go on to the next problem. New Choco(...) tries to find a graph coloring for the given graph (using constraint programming), but if it takes longer than 3 hours, it should move on. – Nicholas Haesen Mar 29 '17 at 18:50

3 Answers3

2

You can get the System time before you start the loop and compare it after each iteration to check if the time is over the specified time, like this:

On for loop starting:

long start = System.currentTimeMillis();

in each iteration:

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

and you have to remove the i++ in the for loop

for (int i = 0; i<7;) {
DZDomi
  • 1,685
  • 15
  • 13
  • Hi, thanks for your help, but if add the if(...) after the new choco(...) line it will first try to complete the new choco(...) line before arriving at the if(...) so it would not work, or am i wrong? – Nicholas Haesen Mar 29 '17 at 18:45
  • 2
    He is looking for a way to interrupt the execution of the current iteration through the loop after x time. Your approach only checks if the time has passed after each iteration, it will never interrupt while iterating. – PlsWork Mar 29 '17 at 18:46
  • Yep, that's pretty much what i'm looking for. – Nicholas Haesen Mar 29 '17 at 18:48
1

You will have to create a new thread which will run your loop, the ExecutorService will run this loop (or whatever code you put into the call() method) for the specified amount of time.

Here is a demo of a task which takes 5 seconds to run, it will be interrupted after 3 seconds:

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).
    }
}
PlsWork
  • 1,958
  • 1
  • 19
  • 31
0

There are many ways of implementing the requested functionality.

One approach could be converting the code in the for to a FutureTask object and submit it to an ExecutorService - even one with just 1 thread, if the loop has to be executed in sequence - e.g.

ExecutorService executor = Executors.newFixedThreadPool(1);

The benefit of having a FutureTask (or any other object implementing the Future interface), is that the cancel() method can be used to make sure that the interrupted iteration will not create any side effects.

For the interrupts, there are numerous alternatives. For example, the javax.swing.Timer class can be used, which fires ActionEvent notifications after the expiry of the timer.

In the above approach, the task (for loop code) will be executed until completion, or until an ActionEvent is received from the timer. In the latter case, a call to cancel() can be used to stop the running task and the next task will start. The counter of the total number of iterations can be maintained at the same place.

For more sophisticated solutions, one can play with the various implementations of ExecutorService and timeout specification options, as in another StackOverflow question.

Community
  • 1
  • 1
PNS
  • 19,295
  • 32
  • 96
  • 143