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
Related
I was curious for my new implementation using ScheduledExecutorService in which the task is expected to finish within 100ms period and 0ms delay. But in case if there is system load and its taking say 550 ms, would there be a queue maintained by ScheduledExecutorService for those pending 4 tasks? And then run as soon as (0ms delay) first one is finished. And what if second execution takes 560 ms , would that add another 4 threads to its queue?
There is not documentation around that, or I might be overlooking it. But I want to make sure that the pile up of such executions would trigger to leak or overflow.
For example: below code, could main thread ever fail?
private static ScheduledExecutorService consumerThreadPool = Executors.newSingleThreadScheduledExecutor();
public static void main(String[] args) throws Exception {
consumerThreadPool.scheduleAtFixedRate(() -> performTask(), 0, 1, TimeUnit.MILLISECONDS);
}
private static void performTask () {
try {
Thread.sleep(550);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Your tasks will be skipped if they overrun the next scheduled time, you can verify easily with System.out.println and alter the sleep under 500ms to 5000ms:
public static void main(final String[] args) throws InterruptedException, ExecutionException
{
var executor = Executors.newScheduledThreadPool(1);
var count = new AtomicInteger();
Runnable task = () -> {
String desc = "run("+((System.currentTimeMillis() / 1000) % 60)+") "+Thread.currentThread().getName()+" count "+count.incrementAndGet();
System.out.println(desc);
if(count.get() == 50)
throw new RuntimeException("I give up!");
try
{
Thread.sleep(2500);
}
catch (InterruptedException e)
{
System.out.println("Thread "+Thread.currentThread().getName()+" INTERRUPTED");
}
};
var future = executor.scheduleAtFixedRate(task, 5000, 1000, TimeUnit.MILLISECONDS);
System.out.println("Calling future.get() ...");
try {
var res = future.get();
System.out.println("future.get()="+res);
}
catch(Exception e)
{
System.err.println("There was an exception:" +e);
// Decide between "continue" or "throw e" here
// ...
}
executor.shutdownNow();
System.out.println("shutdown complete");
}
it's a simple java thread.
there are 2 threads, and it should be printed every 5 second.
there's no error.
but i just can't run.
please help me finding out what's wrong...
class MyThread extends Thread {
String message;
int delay;
public MyThread(String s, int d) {
message = s;
delay = d;
}
public void run() {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
System.out.println(message + "+" + delay );
}
}
}
public class applet {
public static void main(String[] args){
MyThread mt1, mt2;
mt1 = new MyThread("Hello", 5000);
mt2 = new MyThread("Bye ", 10000);
mt1.start();
mt2.start();
}
}
You are printing ONLY ONCE if an exception occurs...
Modify the run method to:
public void run() {
try {
Thread.sleep(delay);
System.out.println(message + "+" + delay );
} catch (InterruptedException e) {
System.err.println("error here" );
}
}
There are actually 2 mistakes in your program:
1. Print your message in the normal flow
So far you only print your message when you get an InterruptedException which is an exception that is thrown when your thread has been interrupted while sleeping. So instead of printing your message in the catch block, you are supposed to print it after the sleep as next:
try {
Thread.sleep(delay);
System.out.println(message + "+" + delay );
} catch (InterruptedException e) {
// Re-set the interrupted flag
Thread.currentThread().interrupt();
}
2. Add an infinite loop
As you wish to print your message every 5 seconds, you need to call sleep in an infinite loop otherwise your thread will print it only once and die, so the code should be at the end:
try {
while (true) {
Thread.sleep(delay);
System.out.printf("%s+%d%n", message, delay);
}
} catch (InterruptedException e) {
// Re-set the interrupted flag
Thread.currentThread().interrupt();
}
3. Bonus
Alternatively, you can use a ScheduledExecutorService to schedule your tasks with a fixed rate using the method scheduleAtFixedRate, your code would then be:
// Create a ScheduledExecutorService of 2 threads
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
// Schedule my task every 5 seconds starting in 5 seconds
executor.scheduleAtFixedRate(new MyTask("Hello", 5000), 5L, 5L, TimeUnit.SECONDS);
// Schedule my task every 10 seconds starting in 10 seconds
executor.scheduleAtFixedRate(new MyTask("Bye ", 10000), 10L, 10L, TimeUnit.SECONDS);
The class MyTask would simply be:
class MyTask implements Runnable {
String message;
int delay;
public MyTask(String s, int d) {
message = s;
delay = d;
}
public void run() {
System.out.printf("%s+%d%n", message, delay);
}
}
SOLVED: Sorry, problem had nothing to do with Java Threads. C3P0's ComboPooledDataSource was creating so many threads and not releasing them. After switching to DBCP2's BasicDataSource, the thread count doesn't go up anymore.
I wrote a web app and it crashes due to not able to create anymore threads. In one of the function, I have the ExecutorService creating a thread pool of 10 threads as a local variable of that function. When I monitor the threads, every time the function is called, about ~12 threads are getting created.
I then moved it to a test file and run this in multiple shells:
public static void main(String[] args) throws Exception {
testRun();
Thread.sleep(1253234234);
}
public static testRun() {
WorkQueue queue = new ThreadPool(10);
for (int i = 0; i < 10; i++) {
queue.addJob(new Runnable() {
#Override
public void run() {
System.out.println(this);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}});
}
queue.startJobs();
queue.wait(10);
}
public void wait(int seconds) {
executor.shutdown();
try {
if (!executor.awaitTermination(seconds, TimeUnit.SECONDS)) {
throw new RuntimeException("Thread pool terminated unexpectedly due to time out.");
}
} catch (InterruptedException ie) {
throw new RuntimeException("Thread interrupt event is received while waiting for termination of ThreadPool - " + ie.getMessage());
}
}
This creates 25 threads in every shell, then release only 10 after it's done. So every time this function is called, there're 15 threads that are not getting released. I'm going to guess the 15 is the maxPoolSize, and the 10 is the corePoolSize. But why aren't they all getting released when function finished?
So I thought maybe I'm not understanding this ExecutorService class and write the raw thread:
public static void main(String[] args) throws Exception {
testRun();
Thread.sleep(1253234234);
}
private static void testRun() throws Exception {
for (int i = 0; i < 10; i++) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5000);
System.out.println(this);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t.start();
}
}
These now creates 27 threads for every shell and release 10 after each function finished. What am I doing wrong? How do I release these threads local to a function? Can someone point me to the right way?
Please ignore compile/syntax error as I replaced the test content after testing it, so this isn't copy and paste off of working code.
Thank you.
In a java class I have a method that sometimes takes a long time for execution. Maybe it hangs in that method flow. What I want is if the method doesn't complete in specific time, the program should exit from that method and continue with the rest of flow.
Please let me know is there any way to handle this situation.
You must use threads in order to achieve this. Threads are not harmful :) Example below run a piece of code for 10 seconds and then ends it.
public class Test {
public static void main(String args[])
throws InterruptedException {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("0");
method();
}
});
thread.start();
long endTimeMillis = System.currentTimeMillis() + 10000;
while (thread.isAlive()) {
if (System.currentTimeMillis() > endTimeMillis) {
System.out.println("1");
break;
}
try {
System.out.println("2");
Thread.sleep(500);
}
catch (InterruptedException t) {}
}
}
static void method() {
long endTimeMillis = System.currentTimeMillis() + 10000;
while (true) {
// method logic
System.out.println("3");
if (System.currentTimeMillis() > endTimeMillis) {
// do some clean-up
System.out.println("4");
return;
}
}
}
}
Execute the method in a different thread, you can end a thread at anytime.
Based on the above snipplet, I tried creating a glorified spring bean.
Such executor runs the passed limitedRuntimeTask in limited runtimeInMs.
If the task finishes within its time limits, the caller continues normally in execution.
If the limitedRuntimeTask fails to finish in the defined runtimeInMs,
the caller will receive the thread execution back. If a timeBreachedTask was defined,
it will be executed before returning to caller.
public class LimitedRuntimeExecutorImpl {
public void runTaskInLessThanGivenMs(int runtimeInMs, final Callable limitedRuntimeTask, final Callable timeBreachedTask) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
LOGGER.info("Started limitedRuntimeTask");
limitedRuntimeTask.call();
LOGGER.info("Finished limitedRuntimeTask in time");
} catch (Exception e) {
LOGGER.error("LimitedRuntimeTask exception", e);
}
}
});
thread.start();
long endTimeMillis = System.currentTimeMillis() + runtimeInMs;
while (thread.isAlive()) {
if (System.currentTimeMillis() > endTimeMillis) {
LOGGER.warn("LmitedRuntimeTask did not finish in time (" + runtimeInMs + ")ms. It will run in vain.");
if(timeBreachedTask != null ){
try {
LOGGER.info("Executing timeBreachedTask");
timeBreachedTask.call();
LOGGER.info("Finished timeBreachedTask");
} catch (Exception e) {
LOGGER.error("timeBreachedTask exception", e);
}
}
return;
}
try {
Thread.sleep(10);
}
catch (InterruptedException t) {}
}
}
}
I feel the approach in accepted answer is a bit outdated. With Java8, it can be done much simpler.
Say, you have a method
MyResult conjureResult(String param) throws MyException { ... }
then you can do this (keep reading, this is just to show the approach):
private final ExecutorService timeoutExecutorService = Executors.newSingleThreadExecutor();
MyResult conjureResultWithTimeout(String param, int timeoutMs) throws Exception {
Future<MyResult> future = timeoutExecutorService.submit(() -> conjureResult(param));
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
}
of course, throwing Exception is bad, here is the correct extended version with proper error processing, but I suggest you examine it carefully, your may want to do some things differently (logging, returning timeout in extended result etc.):
private final ExecutorService timeoutExecutorService = Executors.newSingleThreadExecutor();
MyResult conjureResultWithTimeout(String param, int timeoutMs) throws MyException {
Future<MyResult> future = timeoutExecutorService.submit(() -> conjureResult(param));
try {
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
//something interrupted, probably your service is shutting down
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} catch (ExecutionException e) {
//error happened while executing conjureResult() - handle it
if (e.getCause() instanceof MyException) {
throw (MyException)e.getCause();
} else {
throw new RuntimeException(e);
}
} catch (TimeoutException e) {
//timeout expired, you may want to do something else here
throw new RuntimeException(e);
}
}
Sorry if the question is quite simple. I am a beginner.
I have to create thread that calulates something, while the first thread works the other one have to measure if the first thread calculate the function in specified time. If not, it has to throw exception. Else it returns the answer.
I'd take the java.util.concurrent components - simple example
public void myMethod() {
// select some executor strategy
ExecutorService executor = Executors.newFixedThreadPool(1);
Future f = executor.submit(new Runnable() {
#Override
public void run() {
heresTheMethodToBeExecuted();
}
});
try {
f.get(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// do something clever
} catch (ExecutionException e) {
// do something clever
} catch (TimeoutException e) {
// do something clever
}
}
Have your thread notify a synchronization object when it is done and have your other thread wait x number of milliseconds for it to finish.
public class Main {
private static final Object mThreadLock = new Object();
static class DoTaskThread extends Thread {
public void run() {
try {
int wait = new Random().nextInt(10000);
System.out.println("Waiting " + wait + " ms");
Thread.sleep(wait);
} catch (InterruptedException ex) {
}
synchronized (mThreadLock) {
mThreadLock.notifyAll();
}
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
synchronized (mThreadLock) {
DoTaskThread thread = new DoTaskThread();
thread.start();
try {
// Only wait 2 seconds for the thread to finish
mThreadLock.wait(2000);
} catch (InterruptedException ex) {
}
if (thread.isAlive()) {
throw new RuntimeException("thread took too long");
} else {
System.out.println("Thread finished in time");
}
}
}
}
join is a lot simpler than using a lock.
join (millis)
Waits at most millis milliseconds
for this thread to die. A timeout of 0
means to wait forever.
Example code:
Thread calcThread = new Thread(new Runnable(){
#Override
public void run() {
//some calculation
}
});
calcThread.start();
//wait at most 2secs for the calcThread to finish.
calcThread.join(2000);
//throw an exception if the calcThread hasn't completed.
if(calcThread.isAlive()){
throw new SomeException("calcThread is still running!");
}
Have a look at http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html#awaitTermination(long,%20java.util.concurrent.TimeUnit) which allows you to handle this without dealing with thread synchronization yourself.