Why doesn't finally block execute in a custom scheduler? - java

I am writing a custom bounded scheduler. This should be able to schedule tasks with a given delay. Try to schedule tasks if the bound has been reached, throwing an exception after a timeout. Here is what I have so far:
public class BoundedScheduledExecutor {
private final ScheduledThreadPoolExecutor executor;
private final Semaphore semaphore;
private final int maxWaitSeconds;
private static final Logger LOG = LoggerFactory.getLogger(
BoundedScheduledExecutor.class
);
// constructor omitted
public ScheduledFuture<?> schedule(Runnable task, long delay, TimeUnit unit)
throws Exception {
try {
boolean result = semaphore.tryAcquire(this.maxWaitSeconds, TimeUnit.SECONDS);
LOG.info("result {}", result);
LOG.info("executor {}", this.executor.getActiveCount());
LOG.info("semaphore {}", this.semaphore);
if (result) {
return this.executor.schedule(
() -> {
try {
LOG.info("before run");
task.run();
} finally {
semaphore.release();
}
},
delay,
unit
);
} else {
semaphore.release();
throw new RejectedExecutionException();
}
} catch (RejectedExecutionException e) {
semaphore.release();
throw e;
} catch (InterruptedException e) {
throw e;
}
}
}
The code is based on a similar implementation from Java concurrency in practice. In my test, I am trying to verify that if I have a short task and another task following that, the second one is scheduled once the short task finishes. My test is this:
public void itSchedulesAfterTimeoutWhenQueueIsFull() throws Exception {
this.boundedScheduledExecutor = new BoundedScheduledExecutor(executor, 1, 3);
Runnable blockingTask = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {}
}
};
Runnable simpleTask = new Runnable() {
#Override
public void run() {}
};
this.boundedScheduledExecutor.schedule(blockingTask, 0, TimeUnit.SECONDS);
this.boundedScheduledExecutor.schedule(simpleTask, 5, TimeUnit.SECONDS);
}
But the second call to schedule throws an exception because tryAcquire returns false. I expect my test should succeed because the first task takes 1s and is scheduled right away. The second one is scheduled after 5s, I was expecting the semaphore will be released in between so that the second task can proceed. I noticed that the semaphore is not released in the finally block for the scheduled task. How do I get the semaphore to release after a task is complete? Why doesn't the finally block execute?

return this.executor.schedule(
() -> {
try {
LOG.info("before run");
task.run();
} finally {
semaphore.release();
}
},
delay,
unit
);
This code does not execute the lambda, it just sends it to the executor that will execute it at some time.
Even if the executor starts running the lambda as soon as it receives it, your main code will not wait for it and the return will be applied, even if the lambda is still running the task.
So it may very well be that the first scheduled task still has not been able to release the semaphore before you invoke this method again, unless you are adding additional controls outside of this code.
In fact with your code you cannot have more than one task scheduled at a given time; until the task currently scheduled has not being finished you will not release the semaphor, but you require acquiring it to schedule a new task.

Related

How to start a thread for specific task and run for at most 5 seconds in Java? [duplicate]

I have a method, which writes to the database. The requirement is to make sure that this method does not execute after a certain time elapses. If it returns before that, then nothing should be done.
The one basic approach that I can think of is doing something like this.
public class LimitedRuntime {
public static void writeToDb(){
// writes to the database
}
public static void main(String[] args) {
long totalExecutionTime = 8000L;
long startTime = System.currentTimeMillis();
while(System.currentTimeMillis() - startTime < totalExecutionTime )
{
writeToDb();
}
}
}
One problem with this approach is that even if the method returns before the max total execution time, even then the program halts so as to wait for the time to elapse.
How can I do this better (or maybe more correctly) ? And if we use Thread, how can we find out which Thread executes that method ?
You can do this by sending your job to an executor:
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<?> future = executor.submit(new Runnable() {
#Override
public void run() {
writeToDb(); // <-- your job
}
});
executor.shutdown(); // <-- reject all further submissions
try {
future.get(8, TimeUnit.SECONDS); // <-- wait 8 seconds to finish
} catch (InterruptedException e) { // <-- possible error cases
System.out.println("job was interrupted");
} catch (ExecutionException e) {
System.out.println("caught exception: " + e.getCause());
} catch (TimeoutException e) {
future.cancel(true); // <-- interrupt the job
System.out.println("timeout");
}
// wait all unfinished tasks for 2 sec
if(!executor.awaitTermination(2, TimeUnit.SECONDS)){
// force them to quit by interrupting
executor.shutdownNow();
}
}
There is also an AspectJ solution for that with jcabi-aspects library:
#Timeable(limit = 5, unit = TimeUnit.SECONDS)
public String writeToDb() {
// writeToDb
}
There is an article explaining it further: Limit Java Method Execution Time

How to completely stop / terminate a task that has already been submitted to an ExecutorService in Java?

Problem : I have an use case where I want to cancel a task that has already been submitted to an executor service. future.cancel() is not helpful to me as the task does not go to wait() / sleep() state during the execution. Also, adding isInterrupted() is not scalable because of the following reasons,
Many other services are called during the execution and using isInterrupted() before each call is ugly.
If suppose one of the service calls in one of the submitted tasks takes more than X milliseconds, I would want to abort the task and free up the tread.
Here is a sample code on how I am using future.cancel() right now. Is there a way where I can completely abort the submitted task / kill the thread executing the task in the main() function without disturbing the other submitted tasks.
public class Main {
ExecutorService executorService = newFixedThreadPool(10);
public static void main(String[] args) {
Future<Integer> test = new Main().sample();
try {
test.get(0, java.util.concurrent.TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
System.out.println("Throwing InterruptedException");
} catch (java.util.concurrent.ExecutionException e) {
System.out.println("Throwing ExecutionException");
} catch (java.util.concurrent.TimeoutException e) {
System.out.println("Throwing TimeoutException");
} finally {
System.out.println(test.cancel(true));
}
System.out.println("main() COMPLETED");
}
private Future<Integer> sample() {
return executorService.submit(() -> {
System.out.println("sample() STARTED");
anotherSample();
System.out.println("sample() COMPLETED");
return 1;
});
}
private void anotherSample() throws Exception {
System.out.println("anotherSample() STARTED");
for (int i = 0; i < 100000; i++) {
// do nothing
}
System.out.println("anotherSample() COMPLETED");
}
}
Output :
Throwing TimeoutException
sample() STARTED
anotherSample() STARTED
true
main() COMPLETED
anotherSample() COMPLETED
sample() COMPLETED

Using ScheduledExecutorService, How to Start a Thread without waiting for other thread to complete at fixed interval?

I want to run a task at every particular interval of time regardless of completion of previous thread. And I've used ScheduledExecutorService with the schedule time at every one second. But the problem is, in my Runnable, If I make thread to sleep for 5 seconds, My ScheduledExecuterService also getting executed in every 5 seconds while it supposed to run each thread at 1 second.
It seems like it ScheduledExecuterService is waiting for previous thread to completion. But I want, The task to be triggered at every 1 second no matter what if job inside the task waits for longer time.
Here's is my code.
public class MyTask implements Runnable {
public void run() {
System.out.println("hi there at: "+ new java.util.Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And here's my ScheduledExecutorService Code.
public class JavaScheduledExecutorServiceExample {
public static void main(String[] args) {
ScheduledExecutorService execService = Executors.newScheduledThreadPool(5);
execService.scheduleAtFixedRate(new MyTask(), 0, 1000, TimeUnit.MILLISECONDS);
}
}
Correct me If I'm doing something wrong. And If I'm wrong, is there any alternative to achieve the same? Providing Any best practices could be more helpful :)
"If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute." The behavior you are seeing is consistent with the javadocs
I believe this will perform the way you specified:
public class JavaScheduledExecutorServiceExample {
private static ScheduledExecutorService execService = null;
private static int timesAsleep = 0;
public static class MyTask implements Runnable {
public void run() {
System.out.println("hi there at: "+ new java.util.Date());
// schedule again
execService.schedule(new MyTask(), 1000, TimeUnit.MILLISECONDS);
try {
int i = timesAsleep;
timesAsleep++;
System.out.println("asleep " + i + "----------------------");
Thread.sleep(5000);
System.out.println("awoke " + i + "----------------------");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
execService = Executors.newScheduledThreadPool(5);
execService.schedule(new MyTask(), 1000, TimeUnit.MILLISECONDS);
}
}
Notice the use schedule() instead of scheduleAtFixedRate() on the ScheduledExecutorService instance. It also schedules the next task as soon as it starts the new task.

Halt or kill main method invocation loaded with reflection in Java [duplicate]

I have a method, which writes to the database. The requirement is to make sure that this method does not execute after a certain time elapses. If it returns before that, then nothing should be done.
The one basic approach that I can think of is doing something like this.
public class LimitedRuntime {
public static void writeToDb(){
// writes to the database
}
public static void main(String[] args) {
long totalExecutionTime = 8000L;
long startTime = System.currentTimeMillis();
while(System.currentTimeMillis() - startTime < totalExecutionTime )
{
writeToDb();
}
}
}
One problem with this approach is that even if the method returns before the max total execution time, even then the program halts so as to wait for the time to elapse.
How can I do this better (or maybe more correctly) ? And if we use Thread, how can we find out which Thread executes that method ?
You can do this by sending your job to an executor:
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<?> future = executor.submit(new Runnable() {
#Override
public void run() {
writeToDb(); // <-- your job
}
});
executor.shutdown(); // <-- reject all further submissions
try {
future.get(8, TimeUnit.SECONDS); // <-- wait 8 seconds to finish
} catch (InterruptedException e) { // <-- possible error cases
System.out.println("job was interrupted");
} catch (ExecutionException e) {
System.out.println("caught exception: " + e.getCause());
} catch (TimeoutException e) {
future.cancel(true); // <-- interrupt the job
System.out.println("timeout");
}
// wait all unfinished tasks for 2 sec
if(!executor.awaitTermination(2, TimeUnit.SECONDS)){
// force them to quit by interrupting
executor.shutdownNow();
}
}
There is also an AspectJ solution for that with jcabi-aspects library:
#Timeable(limit = 5, unit = TimeUnit.SECONDS)
public String writeToDb() {
// writeToDb
}
There is an article explaining it further: Limit Java Method Execution Time

How do I call some blocking method with a timeout in Java?

Is there a standard nice way to call a blocking method with a timeout in Java? I want to be able to do:
// call something.blockingMethod();
// if it hasn't come back within 2 seconds, forget it
if that makes sense.
Thanks.
You could use an Executor:
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
public Object call() {
return something.blockingMethod();
}
};
Future<Object> future = executor.submit(task);
try {
Object result = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException ex) {
// handle the timeout
} catch (InterruptedException e) {
// handle the interrupts
} catch (ExecutionException e) {
// handle other exceptions
} finally {
future.cancel(true); // may or may not desire this
}
If the future.get doesn't return in 5 seconds, it throws a TimeoutException. The timeout can be configured in seconds, minutes, milliseconds or any unit available as a constant in TimeUnit.
See the JavaDoc for more detail.
You could wrap the call in a FutureTask and use the timeout version of get().
See http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/FutureTask.html
See also Guava's TimeLimiter which uses an Executor behind the scenes.
It's really great that people try to implement this in so many ways. But the truth is, there is NO way.
Most developers would try to put the blocking call in a different thread and have a future or some timer. BUT there is no way in Java to stop a thread externally, let alone a few very specific cases like the Thread.sleep() and Lock.lockInterruptibly() methods that explicitly handle thread interruption.
So really you have only 3 generic options:
Put your blocking call on a new thread and if the time expires you just move on, leaving that thread hanging. In that case you should make sure the thread is set to be a Daemon thread. This way the thread will not stop your application from terminating.
Use non blocking Java APIs. So for network for example, use NIO2 and use the non blocking methods. For reading from the console use Scanner.hasNext() before blocking etc.
If your blocking call is not an IO, but your logic, then you can repeatedly check for Thread.isInterrupted() to check if it was interrupted externally, and have another thread call thread.interrupt() on the blocking thread
This course about concurrency https://www.udemy.com/java-multithreading-concurrency-performance-optimization/?couponCode=CONCURRENCY
really walks through those fundamentals if you really want to understand how it works in Java. It actually talks about those specific limitations and scenarios, and how to go about them in one of the lectures.
I personally try to program without using blocking calls as much as possible. There are toolkits like Vert.x for example that make it really easy and performant to do IO and no IO operations asynchronously and in a non blocking way.
I hope it helps
There is also an AspectJ solution for that with jcabi-aspects library.
#Timeable(limit = 30, unit = TimeUnit.MINUTES)
public Soup cookSoup() {
// Cook soup, but for no more than 30 minutes (throw and exception if it takes any longer
}
It can't get more succinct, but you have to depend on AspectJ and introduce it in your build lifecycle, of course.
There is an article explaining it further: Limit Java Method Execution Time
I'm giving you here the complete code. In place of the method I'm calling, you can use your method:
public class NewTimeout {
public String simpleMethod() {
return "simple method";
}
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Callable<Object> task = new Callable<Object>() {
public Object call() throws InterruptedException {
Thread.sleep(1100);
return new NewTimeout().simpleMethod();
}
};
Future<Object> future = executor.submit(task);
try {
Object result = future.get(1, TimeUnit.SECONDS);
System.out.println(result);
} catch (TimeoutException ex) {
System.out.println("Timeout............Timeout...........");
} catch (InterruptedException e) {
// handle the interrupts
} catch (ExecutionException e) {
// handle other exceptions
} finally {
executor.shutdown(); // may or may not desire this
}
}
}
Thread thread = new Thread(new Runnable() {
public void run() {
something.blockingMethod();
}
});
thread.start();
thread.join(2000);
if (thread.isAlive()) {
thread.stop();
}
Note, that stop is deprecated, better alternative is to set some volatile boolean flag, inside blockingMethod() check it and exit, like this:
import org.junit.*;
import java.util.*;
import junit.framework.TestCase;
public class ThreadTest extends TestCase {
static class Something implements Runnable {
private volatile boolean stopRequested;
private final int steps;
private final long waitPerStep;
public Something(int steps, long waitPerStep) {
this.steps = steps;
this.waitPerStep = waitPerStep;
}
#Override
public void run() {
blockingMethod();
}
public void blockingMethod() {
try {
for (int i = 0; i < steps && !stopRequested; i++) {
doALittleBit();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public void doALittleBit() throws InterruptedException {
Thread.sleep(waitPerStep);
}
public void setStopRequested(boolean stopRequested) {
this.stopRequested = stopRequested;
}
}
#Test
public void test() throws InterruptedException {
final Something somethingRunnable = new Something(5, 1000);
Thread thread = new Thread(somethingRunnable);
thread.start();
thread.join(2000);
if (thread.isAlive()) {
somethingRunnable.setStopRequested(true);
thread.join(2000);
assertFalse(thread.isAlive());
} else {
fail("Exptected to be alive (5 * 1000 > 2000)");
}
}
}
You need a circuit breaker implementation like the one present in the failsafe project on GitHub.
Try this. More simple solution. Guarantees that if block didn't execute within the time limit. the process will terminate and throws an exception.
public class TimeoutBlock {
private final long timeoutMilliSeconds;
private long timeoutInteval=100;
public TimeoutBlock(long timeoutMilliSeconds){
this.timeoutMilliSeconds=timeoutMilliSeconds;
}
public void addBlock(Runnable runnable) throws Throwable{
long collectIntervals=0;
Thread timeoutWorker=new Thread(runnable);
timeoutWorker.start();
do{
if(collectIntervals>=this.timeoutMilliSeconds){
timeoutWorker.stop();
throw new Exception("<<<<<<<<<<****>>>>>>>>>>> Timeout Block Execution Time Exceeded In "+timeoutMilliSeconds+" Milli Seconds. Thread Block Terminated.");
}
collectIntervals+=timeoutInteval;
Thread.sleep(timeoutInteval);
}while(timeoutWorker.isAlive());
System.out.println("<<<<<<<<<<####>>>>>>>>>>> Timeout Block Executed Within "+collectIntervals+" Milli Seconds.");
}
/**
* #return the timeoutInteval
*/
public long getTimeoutInteval() {
return timeoutInteval;
}
/**
* #param timeoutInteval the timeoutInteval to set
*/
public void setTimeoutInteval(long timeoutInteval) {
this.timeoutInteval = timeoutInteval;
}
}
example :
try {
TimeoutBlock timeoutBlock = new TimeoutBlock(10 * 60 * 1000);//set timeout in milliseconds
Runnable block=new Runnable() {
#Override
public void run() {
//TO DO write block of code
}
};
timeoutBlock.addBlock(block);// execute the runnable block
} catch (Throwable e) {
//catch the exception here . Which is block didn't execute within the time limit
}
In special case of a blocking queue:
Generic java.util.concurrent.SynchronousQueue has a poll method with timeout parameter.
Assume blockingMethod just sleep for some millis:
public void blockingMethod(Object input) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
My solution is to use wait() and synchronized like this:
public void blockingMethod(final Object input, long millis) {
final Object lock = new Object();
new Thread(new Runnable() {
#Override
public void run() {
blockingMethod(input);
synchronized (lock) {
lock.notify();
}
}
}).start();
synchronized (lock) {
try {
// Wait for specific millis and release the lock.
// If blockingMethod is done during waiting time, it will wake
// me up and give me the lock, and I will finish directly.
// Otherwise, when the waiting time is over and the
// blockingMethod is still
// running, I will reacquire the lock and finish.
lock.wait(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
So u can replace
something.blockingMethod(input)
to
something.blockingMethod(input, 2000)
Hope it helps.

Categories