How set a timeout for my thread Handler method? - java

This is my function who run a code every 2.5 seconds and check if a value seted to the true my progress will gone and ...
mHandler = new Handler();
continue_or_stop = true;
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (continue_or_stop) {
try {
Thread.sleep(2500); // every 2.5 seconds
mHandler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
if (sp.getFromPreferences("state_update").equals("true")) {
progress_main.setVisibility(View.GONE);
layout_main.setVisibility(View.VISIBLE);
btn_save_send.setVisibility(View.GONE);
getOutputs();
MDToast.makeText(getActivity(), "وضعیت دستگاه با موفقیت بروزرسانی شد", Toast.LENGTH_LONG, MDToast.TYPE_SUCCESS).show();
sp.saveToPreferences("state_update", "false");
Intent intent = new Intent(getContext(), MainActivity.class);
startActivity(intent);
}
// you can set continue_or_stop to false, for stop
}
});
} catch (Exception e) {
// TODO: handle exception
}
}
}
}).start();
now i want a time out for this method if the value not seted to true after a (for example 12 seconds) progress should gone and Toast it to user that something goes wrong and try again

You can check for the timeout based on the number of trials. Also using thread and Thread.sleep for running a periodic task is not a good practice.
To run a periodic task, you can post a Runnable to a Handler with some delay using postDelayed method.
private Handler mHandler = new Handler();
private int mTrials = 0;
private Runnable mPeriodicTask = new Runnable() {
public void run() {
// Do the check
mTrials += 1;
if (mTrials == /* timeout number */) {
// timeout
} else {
mHandler.postDelayed(this, 2500);
}
}
}
To run the task:
mHandler.postDelayed(mPeriodicTask, 2500);

Apparently this is more Android oriented, but I'll answer in general terms. And the other answer seems lacking the "12 seconds" timeout.
Well, you cannot really terminate a Thread immediatly, or forcely. Consider a Thread like a person, you need to kindly request him to terminate what he's doing. If he is able to do that, he will terminate, if not he will continue with its task.
As you're building the implementation of the task, you can check if someone asked you to terminate, with a special flag
Thread#isInterrupted()
Now, for this kind of thing using an ExecutorService is the better option, as it returns a Future<T> which can be canceled. E.g.
final ExecutorService executorService = ExecutorService.newSingleThreadExecutor();
final Future<?> future = executorService.submit(runnable);
You can then say to the Future "I want the result (which in your case is nothing), but with a timeout"
try {
future.get(12, TimeUnit.SECONDS);
} catch (final TimeoutException e) {
future.cancel(true);
}
The cancel(true) method call will set the interrupted flag of the Thread.
Now, maintaining the code you already have, you might simply want to replace
while (continue_or_stop)
with
while (!Thread.currentThread().isInterrupted())
Adjust to your needs.

Related

How to terminate a process after a certain time? [duplicate]

How to set a Timer, say for 2 minutes, to try to connect to a Database then throw exception if there is any issue in connection?
So the first part of the answer is how to do what the subject asks as this was how I initially interpreted it and a few people seemed to find helpful. The question was since clarified and I've extended the answer to address that.
Setting a timer
First you need to create a Timer (I'm using the java.util version here):
import java.util.Timer;
..
Timer timer = new Timer();
To run the task once you would do:
timer.schedule(new TimerTask() {
#Override
public void run() {
// Your database code here
}
}, 2*60*1000);
// Since Java-8
timer.schedule(() -> /* your database code here */, 2*60*1000);
To have the task repeat after the duration you would do:
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Your database code here
}
}, 2*60*1000, 2*60*1000);
// Since Java-8
timer.scheduleAtFixedRate(() -> /* your database code here */, 2*60*1000, 2*60*1000);
Making a task timeout
To specifically do what the clarified question asks, that is attempting to perform a task for a given period of time, you could do the following:
ExecutorService service = Executors.newSingleThreadExecutor();
try {
Runnable r = new Runnable() {
#Override
public void run() {
// Database task
}
};
Future<?> f = service.submit(r);
f.get(2, TimeUnit.MINUTES); // attempt the task for two minutes
}
catch (final InterruptedException e) {
// The thread was interrupted during sleep, wait or join
}
catch (final TimeoutException e) {
// Took too long!
}
catch (final ExecutionException e) {
// An exception from within the Runnable task
}
finally {
service.shutdown();
}
This will execute normally with exceptions if the task completes within 2 minutes. If it runs longer than that, the TimeoutException will be throw.
One issue is that although you'll get a TimeoutException after the two minutes, the task will actually continue to run, although presumably a database or network connection will eventually time out and throw an exception in the thread. But be aware it could consume resources until that happens.
Use this
long startTime = System.currentTimeMillis();
long elapsedTime = 0L.
while (elapsedTime < 2*60*1000) {
//perform db poll/check
elapsedTime = (new Date()).getTime() - startTime;
}
//Throw your exception
Ok, I think I understand your problem now. You can use a Future to try to do something and then timeout after a bit if nothing has happened.
E.g.:
FutureTask<Void> task = new FutureTask<Void>(new Callable<Void>() {
#Override
public Void call() throws Exception {
// Do DB stuff
return null;
}
});
Executor executor = Executors.newSingleThreadScheduledExecutor();
executor.execute(task);
try {
task.get(5, TimeUnit.SECONDS);
}
catch(Exception ex) {
// Handle your exception
}
new java.util.Timer().schedule(new TimerTask(){
#Override
public void run() {
System.out.println("Executed...");
//your code here
//1000*5=5000 mlsec. i.e. 5 seconds. u can change accordngly
}
},1000*5,1000*5);
[Android] if someone looking to implement timer on android using java.
you need use UI thread like this to perform operations.
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
ActivityName.this.runOnUiThread(new Runnable(){
#Override
public void run() {
// do something
}
});
}
}, 2000));

How to detect an unknown thread pool and shut it down?

I need to set a timeout for a block of code which will call an method in jar file.
I am using the following code
final Runnable stuffToDo = new Runnable() {
#Override
public void run() {
/* Do stuff here. */
jarclass.run();
}
};
final ExecutorService executor = Executors.newFixedThreadPool(1);
final Future future = executor.submit(stuffToDo);
//executor.shutdown(); // This does not cancel the already-scheduled task.
try {
future.get(1, TimeUnit.SECONDS);
}
catch (InterruptedException ie) {
/* Handle the interruption. Or ignore it. */
}
catch (ExecutionException ee) {
/* Handle the error. Or ignore it. */
}
catch (TimeoutException te) {
/* Handle the timeout. Or ignore it. */
}
if (!executor.isTerminated()){
executor.shutdownNow();
}
However the jarclass.run() somehow start another thread which keep running and show all the printout with pool-2-thread-1.
How can I completely shutdown the jarclass.run()??
Update:
I changed new Thread() to new Runnable. It still doesn't work.
What I am confusing is I don't know where jarclass start another thread and cannot handle it. When the code goes to executor.shutdownNow(), it does jump out and run the following code. But the jarclass.run() are still running.
I am not very good at English. Hope I made this clear.
Update:
Problem solved by this code:
Future<String> future = new FutureTask<String>(new Callable<String>() {
public String call() throws Exception {
jarclass.run();
return null;
}
});
try {
future.get(1, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
Don't know why the former code fail......If anyone knows, we can still discuss.
Thanks for all the kindly replies. Really appreciate it.
You should not instantiate a Thread when using ExecutorService. Use Runnable instead:
final Runnable stuffToDo = new Runnable() { /* as it is now */ };
When you create a thread directly, it's not managed by the executor service you create later and that's why all the logs.
It's not safe kill thread directly, see Thread.stop() deprecated
Recomended way it to use a flag that can notify to thread that is time to stop.
If you can access to jar and modify code you can create a method named stop() in your jarclass using flag so when you need to kill process you can call jarclass.stop().
For example:
public class jarclass{
private boolean keepAlive = true;
public void run(){
keepAlive = true;
while(keepAlive){
//do work
}
}
public void stop(){
keepAlive = false;
}
}

Can't stop thread

I have these two methods for creating and stopping a thread. However the thread still keeps running, even after the first method is called. (I'm creating an object of the class and calling them from another class).
private Thread thread;
public void stopAlarm() {
Log.i(LOG_TAG, "stopAlarm called");
sendAlarm = false;
if (!thread.equals(null)) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void triggerAlarm() {
Runnable alarmTest = new Runnable() {
#Override
public void run() {
while (sendAlarm) {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
}
}
};
thread = new Thread(Test);
thread.start();
}
When stopAlarm is called the thread is always null, although it is called after triggerAlarm is called (thread is running).
Your problem is caused by thread scope. Thread scope is created when you create a thread with same variables in the scope but you can't change these variables from outside world. Best practice for managing runnables in android is to use Handler.
Handler handler = new Handler();
Runnable alarmTest = new Runnable() {
#Override
public void run() {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
handler.post(alarmTest, 5000); //wait 5 sec and run again
//you can stop from outside
}
};
after definitions, in order to start the runnable:
handler.post(alarmTest,0); //wait 0 ms and run
in order to stop the runnable:
handler.removeCallbacks(alarmTest);
EDIT: wait statement with loop
EDIT: Complete solution
Handler handler = new Handler();
Runnable alarmTest = new Runnable() {
#Override
public void run() {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
handler.post(alarmTest, 5000); //wait 5 sec and run again
//you can stop from outside
}
};
public void stopAlarm() {
Log.i(LOG_TAG, "stopAlarm called");
handler.removeCallbacks(alarmTest);
}
public void triggerAlarm() {
handler.post(alarmTest,0); //wait 0 ms and run
}
Depending on your OS you may find making your thread volatile may fix this.
private volatile Thread thread;
However - there are better ways to do this. One very useful one is using a small (just one entry) BlockingQueue which is polled by the running thread.
// Use a BlockingQueue to signal the alarm to stop.
BlockingQueue<String> stop = new ArrayBlockingQueue<>(1);
public void stopAlarm() {
stop.add("Stop");
}
public void triggerAlarm() {
new Thread(() -> {
try {
while (stop.poll(1, TimeUnit.SECONDS) == null) {
// Stuff
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
Clearly you will have to manage edge cases like where someone calls stopAlarm when no alarm is running.

Auto execute message every 5 seconds

I am new to Android. Can anyone tell me how to execute a message every 5 seconds. I have tried this code, but it's not showing anything on my emulator. What should I be doing instead?
while(true) {
Toast.makeText(this, "hi", Toast.LENGTH_SHORT).show();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
You should not call Thread.sleep() from the GUI thread. Never do this. Use a handler for such thing.
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
public void run() {
doStuff();
/*
* Now register it for running next time
*/
handler.postDelayed(this, 1000);
}
};
I prefer this way to using timers because the Timer class introduces a new thread and it is now fair to do this.
Is that the sum of your code? What are you setting your activity view to? Android implements an alarm/scheduling service which will be much more friendly to battery life than trying to implement your own.

Java: set timeout on a certain block of code?

Is it possible to force Java to throw an Exception after some block of code runs longer than acceptable?
Here's the simplest way that I know of to do this:
final Runnable stuffToDo = new Thread() {
#Override
public void run() {
/* Do stuff here. */
}
};
final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future future = executor.submit(stuffToDo);
executor.shutdown(); // This does not cancel the already-scheduled task.
try {
future.get(5, TimeUnit.MINUTES);
}
catch (InterruptedException ie) {
/* Handle the interruption. Or ignore it. */
}
catch (ExecutionException ee) {
/* Handle the error. Or ignore it. */
}
catch (TimeoutException te) {
/* Handle the timeout. Or ignore it. */
}
if (!executor.isTerminated())
executor.shutdownNow(); // If you want to stop the code that hasn't finished.
Alternatively, you can create a TimeLimitedCodeBlock class to wrap this functionality, and then you can use it wherever you need it as follows:
new TimeLimitedCodeBlock(5, TimeUnit.MINUTES) { #Override public void codeBlock() {
// Do stuff here.
}}.run();
I compiled some of the other answers into a single utility method:
public class TimeLimitedCodeBlock {
public static void runWithTimeout(final Runnable runnable, long timeout, TimeUnit timeUnit) throws Exception {
runWithTimeout(new Callable<Object>() {
#Override
public Object call() throws Exception {
runnable.run();
return null;
}
}, timeout, timeUnit);
}
public static <T> T runWithTimeout(Callable<T> callable, long timeout, TimeUnit timeUnit) throws Exception {
final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future<T> future = executor.submit(callable);
executor.shutdown(); // This does not cancel the already-scheduled task.
try {
return future.get(timeout, timeUnit);
}
catch (TimeoutException e) {
//remove this if you do not want to cancel the job in progress
//or set the argument to 'false' if you do not want to interrupt the thread
future.cancel(true);
throw e;
}
catch (ExecutionException e) {
//unwrap the root cause
Throwable t = e.getCause();
if (t instanceof Error) {
throw (Error) t;
} else if (t instanceof Exception) {
throw (Exception) t;
} else {
throw new IllegalStateException(t);
}
}
}
}
Sample code making use of this utility method:
public static void main(String[] args) throws Exception {
final long startTime = System.currentTimeMillis();
log(startTime, "calling runWithTimeout!");
try {
TimeLimitedCodeBlock.runWithTimeout(new Runnable() {
#Override
public void run() {
try {
log(startTime, "starting sleep!");
Thread.sleep(10000);
log(startTime, "woke up!");
}
catch (InterruptedException e) {
log(startTime, "was interrupted!");
}
}
}, 5, TimeUnit.SECONDS);
}
catch (TimeoutException e) {
log(startTime, "got timeout!");
}
log(startTime, "end of main method!");
}
private static void log(long startTime, String msg) {
long elapsedSeconds = (System.currentTimeMillis() - startTime);
System.out.format("%1$5sms [%2$16s] %3$s\n", elapsedSeconds, Thread.currentThread().getName(), msg);
}
Output from running the sample code on my machine:
0ms [ main] calling runWithTimeout!
13ms [ pool-1-thread-1] starting sleep!
5015ms [ main] got timeout!
5016ms [ main] end of main method!
5015ms [ pool-1-thread-1] was interrupted!
Yes, but its generally a very bad idea to force another thread to interrupt on a random line of code. You would only do this if you intend to shutdown the process.
What you can do is to use Thread.interrupt() for a task after a certain amount of time. However, unless the code checks for this it won't work. An ExecutorService can make this easier with Future.cancel(true)
Its much better for the code to time itself and stop when it needs to.
If it is test code you want to time, then you can use the time attribute:
#Test(timeout = 1000)
public void shouldTakeASecondOrLess()
{
}
If it is production code, there is no simple mechanism, and which solution you use depends upon whether you can alter the code to be timed or not.
If you can change the code being timed, then a simple approach is is to have your timed code remember it's start time, and periodically the current time against this. E.g.
long startTime = System.currentTimeMillis();
// .. do stuff ..
long elapsed = System.currentTimeMillis()-startTime;
if (elapsed>timeout)
throw new RuntimeException("tiomeout");
If the code itself cannot check for timeout, you can execute the code on another thread, and wait for completion, or timeout.
Callable<ResultType> run = new Callable<ResultType>()
{
#Override
public ResultType call() throws Exception
{
// your code to be timed
}
};
RunnableFuture<ResultType> future = new FutureTask<>(run);
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(future);
ResultType result = null;
try
{
result = future.get(1, TimeUnit.SECONDS); // wait 1 second
}
catch (TimeoutException ex)
{
// timed out. Try to stop the code if possible.
future.cancel(true);
}
service.shutdown();
}
I can suggest two options.
Within the method, assuming it is looping and not waiting for an external event, add a local field and test the time each time around the loop.
void method() {
long endTimeMillis = System.currentTimeMillis() + 10000;
while (true) {
// method logic
if (System.currentTimeMillis() > endTimeMillis) {
// do some clean-up
return;
}
}
}
Run the method in a thread, and have the caller count to 10 seconds.
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
method();
}
});
thread.start();
long endTimeMillis = System.currentTimeMillis() + 10000;
while (thread.isAlive()) {
if (System.currentTimeMillis() > endTimeMillis) {
// set an error flag
break;
}
try {
Thread.sleep(500);
}
catch (InterruptedException t) {}
}
The drawback to this approach is that method() cannot return a value directly, it must update an instance field to return its value.
EDIT: Peter Lawrey is completely right: it's not as simple as interrupting a thread (my original suggestion), and Executors & Callables are very useful ...
Rather than interrupting threads, you could set a variable on the Callable once the timeout is reached. The callable should check this variable at appropriate points in task execution, to know when to stop.
Callables return Futures, with which you can specify a timeout when you try to 'get' the future's result. Something like this:
try {
future.get(timeoutSeconds, TimeUnit.SECONDS)
} catch(InterruptedException e) {
myCallable.setStopMeAtAppropriatePlace(true);
}
See Future.get, Executors, and Callable ...
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html#get-long-java.util.concurrent.TimeUnit-
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Callable.html
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool%28int%29
I created a very simple solution without using any frameworks or APIs. This looks more elegant and understandable. The class is called TimeoutBlock.
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 to execute
}
};
timeoutBlock.addBlock(block);// execute the runnable block
} catch (Throwable e) {
//catch the exception here . Which is block didn't execute within the time limit
}
This was so much useful for me when i had to connect to a FTP account. Then download and upload stuff. sometimes FTP connection hangs or totally breaks. This caused whole system to go down. and i needed a way to detect it and prevent it from happening . So i created this and used it. Works pretty well.
I faced a similar kind of issue where my task was to push a message to SQS within a particular timeout. I used the trivial logic of executing it via another thread and waiting on its future object by specifying the timeout. This would give me a TIMEOUT exception in case of timeouts.
final Future<ISendMessageResult> future =
timeoutHelperThreadPool.getExecutor().submit(() -> {
return getQueueStore().sendMessage(request).get();
});
try {
sendMessageResult = future.get(200, TimeUnit.MILLISECONDS);
logger.info("SQS_PUSH_SUCCESSFUL");
return true;
} catch (final TimeoutException e) {
logger.error("SQS_PUSH_TIMEOUT_EXCEPTION");
}
But there are cases where you can't stop the code being executed by another thread and you get true negatives in that case.
For example - In my case, my request reached SQS and while the message was being pushed, my code logic encountered the specified timeout. Now in reality my message was pushed into the Queue but my main thread assumed it to be failed because of the TIMEOUT exception.
This is a type of problem which can be avoided rather than being solved. Like in my case I avoided it by providing a timeout which would suffice in nearly all of the cases.
If the code you want to interrupt is within you application and is not something like an API call then you can simply use
future.cancel(true)
However do remember that java docs says that it does guarantee that the execution will be blocked.
"Attempts to cancel execution of this task. This attempt will fail if the task has already completed, has already been cancelled,or could not be cancelled for some other reason. If successful,and this task has not started when cancel is called,this task should never run. If the task has already started,then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted inan attempt to stop the task."
If you want a CompletableFuture way you could have a method like
public MyResponseObject retrieveDataFromEndpoint() {
CompletableFuture<MyResponseObject> endpointCall
= CompletableFuture.supplyAsync(() ->
yourRestService.callEnpoint(withArg1, withArg2));
try {
return endpointCall.get(10, TimeUnit.MINUTES);
} catch (TimeoutException
| InterruptedException
| ExecutionException e) {
throw new RuntimeException("Unable to fetch data", e);
}
}
If you're using spring, you could annotate the method with a #Retryable so that it retries the method three times if an exception is thrown.
Instead of having the task in the new thread and the timer in the main thread, have the timer in the new thread and the task in the main thread:
public static class TimeOut implements Runnable{
public void run() {
Thread.sleep(10000);
if(taskComplete ==false) {
System.out.println("Timed Out");
return;
}
else {
return;
}
}
}
public static boolean taskComplete = false;
public static void main(String[] args) {
TimeOut timeOut = new TimeOut();
Thread timeOutThread = new Thread(timeOut);
timeOutThread.start();
//task starts here
//task completed
taskComplete =true;
while(true) {//do all other stuff }
}
There is a hacky way to do it.
Set some boolean field to indicate whether the work was completed. Then before the block of code, set a timer to run a piece of code after your timeout. The timer will check if the block of code had finished executing, and if not, throw an exception. Otherwise it will do nothing.
The end of the block of code should, of course, set the field to true to indicate the work was done.
There's a very simple option that nobody's mentioned yet:
Duration timeout = Duration.ofMinutes(5);
Thread thread = new Thread(() -> {
// your code here
});
thread.start();
thread.join(timeout.toMillis());
if (thread.isAlive()) {
thread.interrupt();
throw new MyTimeoutException();
}
If the thread running your code block fails to complete within the timeout, it is interrupted and whatever exception you want can be thrown.
It is possible to write code that will simply ignore the interruption and carry on. If you're dealing with this can cannot fix it then there is thread.stop(), but that can break any synchronisation mechanisms that you are relying on. See its deprecation notice.
You can also capture exceptions from the thread:
AtomicReference<Throwable> uncaughtException = new AtomicReference<>();
thread.setUncaughtExceptionHandler((t, ex) -> uncaughtException.setRelease(ex));
// ...
Throwable ex = uncaughtException.getAcquire();
if (ex != null) {
throw ex;
}
I had this problem too, my logs print out with ‘’Unexpected end of stream‘’.and ‘’Could not get a resource from the pool‘’,
I set the timeout of brpop to 30s, redis to 31s, and mysql database connection pool to 300s. For now, this error is not printed on the log, but I don't know if this error will be reported in the future.I don't know if it has a bad effect on my writing to the database

Categories

Resources