1

I want to restrict the execution time of a method in java, I want my particular method that If it is executed in some certain defined time then ok otherwise it should throw an exception.

For this I tried using as :

@Timeable(limit = 1000, unit = TimeUnit.MILLISECONDS)
public void testMethod(){
    try {
            Thread.sleep(2000);
            if (Thread.interrupted()) {
                  throw new InterruptedException();
            }
        }catch(InterruptedException e1){
            logger.error("failed due to-" + e1, e1.getMessage());
            throw new InterruptedException(e1.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new Exception(e.getMessage());
        }
}

For this I took reference from : http://www.yegor256.com/2014/06/20/limit-method-execution-time.html

It should throw the exception after the line:

Thread.sleep(2000);

But this my code is not throwing the exception.

Please help what is missing.

Thanks in advance for any other suggested approach for the same purpose.

Vikas Taank
  • 101
  • 1
  • 12
  • 1
    Did you weave your class, as described in the page you linked to? – Dawood ibn Kareem Aug 17 '17 at 08:12
  • Such annotation work not by-self, but in concrete environment. Read in blogs libraries, exacly configuration and way of use – Jacek Cz Aug 17 '17 at 08:13
  • The corresponding question is not a good duplicate, but [this answer](https://stackoverflow.com/a/45433655/7598776) may still be helpful – Robin Topper Aug 17 '17 at 08:13
  • Yes @Jacek Cz , for making the required libraries available, I have added this gradle dependency : compile group: 'com.jcabi', name: 'jcabi-aspects', version: '0.22' – Vikas Taank Aug 17 '17 at 08:14
  • @DawoodibnKareem I have added same configs on class as described on the page I linked to my question. Some other changes suggested by you?? – Vikas Taank Aug 17 '17 at 08:39
  • If one of the answers below fixes your issue, you should accept it (click the check mark next to the appropriate answer). That does two things. It lets everyone know your issue has been resolved to your satisfaction, and it gives the person that helps you credit for the assist. [See here](http://meta.stackexchange.com/a/5235) for a full explanation. – Robin Topper Aug 17 '17 at 11:06

3 Answers3

3

For the approach you're using, it isn't sufficient to add @Timeable annotations, you also need to configure aspect weaving as described on Weaving Java Binaries.

It's interesting to note that the blog post author and creator of jcabi-aspects, Yegor Bugayenko, has since decided that Java annotations are a big mistake.

Another approach is to use CompletableFuture:

public void testMethod() {
    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("Interrupted", e);
        }
    });
    try {
        future.get(1000, TimeUnit.MILLISECONDS);
    } catch (TimeoutException e) {
        // Operation timed out. Cancel it and log.
        future.cancel(true);
        logger.error("Timed out", e);
    } catch (InterruptedException e) {
        // Current thread interrupted while waiting. Cancel operation and log.
        future.cancel(true);
        logger.error("Interrupted", e);
        // Reassert interrupt flag, since exception is not propagated.
        Thread.currentThread().interrupt();
    } catch (ExecutionException e) {
        logger.error("Operation failed", e.getCause());
        // No need to cancel in this case, since the operation has completed.
    }
}

Note that the code always reasserts interrupt status when catching InterruptedException. See Why invoke Thread.currentThread.interrupt() in a catch InterruptException block?

Also note that the operation is explicitly cancelled if it times out or the calling thread is interrupted, to avoid wasting resources.

markusk
  • 6,477
  • 34
  • 39
2

As already mentioned in the comments, this solution seems to be usuable in your case as well. It would look like this:

public void testMethod() {
    ForkJoinPool forkJoinPool = new ForkJoinPool(1);
    try {
        forkJoinPool.submit(() ->
        {
        // replace the following linea with the actual code that should be in this method
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {}
            System.out.println("Job done");
        })
        // wait for x milliseconds before wait times out and TimeOutException is thrown
                .get(1000, TimeUnit.MILLISECONDS);
    } catch (TimeoutException e) {
        // job not done in your interval
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    } 
}

Since the Thread#sleep takes 2 seconds, which is more than the 1 second wait time out specified in the .get(...), this method will always time out in this example.

Robin Topper
  • 2,295
  • 1
  • 17
  • 25
0

Here is the code and its self explanatory: For testing purpose I have just written s simple method that will execute for only 3 seconds.

import java.util.Timer;
import java.util.TimerTask;

class Test {

    Timer timer;

    public Test(int seconds) {
        timer = new Timer();
        timer.schedule(new RemindTask(), seconds * 1000);
    }

    class RemindTask extends TimerTask {
        public void run() {
            System.out.format("Time's up!%n");
            System.exit(0);
            timer.cancel();
        }
    }

    public static void main(String args[]) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                 new Test(3);
                 sum();
                 System.out.format("Task scheduled.%n");
            }
        });
       t.start();
    }

    public static void sum(){
        for(int i = 0 ; i < 100 ;i++){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(i);
        }
    }
}
Abhishek Honey
  • 645
  • 4
  • 13
  • You can also see the link https://stackoverflow.com/questions/15747277/how-to-make-java-program-exit-after-a-couple-of-seconds – Abhishek Honey Aug 17 '17 at 09:28