I am currently facing a challenge with executing following thread in my webapplication:
return new Runnable() {
#Override
public void run() {
long lastHeartBeat = -1;
while (true) {
if (isFullAbortRequested()) {
break;
}
if (lastHeartBeat == -1 || lastHeartBeat + 1000 * 60 < new Date().getTime()) {
// once every x minutes send a "i'm still alive!"
DEFAULT_LOGGER.info("still alive!");
lastHeartBeat = new Date().getTime();
}
//DO SOMETHING THAT TAKES 1 MIN
try {
Thread.sleep(1000);
} catch (final InterruptedException e) {
DEFAULT_LOGGER.error("CACHE REFRESH SERVICE DOWN");
}
}
}
};
The problem with this one, is that after some days it just stops (without any known reason). Is this a "expected behaviour" on such "while(true) sleep" threads that they might be closed by OS (?) or anything else?
What would be a durable solution for this "check every second if you have to do something, and if yes, do it (can take 1 min). then wait a second before next check"? The actions in "DO SOMETHING" should never parallize or overlap, so they should be blocking for this thread.
Thank you in advance!
Related
I have a questions game ready in Java, with a counter time for each question. Players have 10 seconds to answer each question. To implement the counter, I maked a Clock class that calls the bot (the game implementer class) using a command class that sends the message "upgrade the countdown screen" (each pulse can call the game to update screen data with the new time left, so players can see the countdown 9, 8, 7 ...).
When clock ends, sends a message "show results and ask new question".
private class Clock extends Thread {
CommandMessage endClock = null;
CommandMessage pulseClock = null;
BotTrivial bot;
long seconds = 10L;
long restSeconds = seconds; //To show how many seconds left to end the counter.
boolean isCancelled = false;
#Override
public void run() {
this.setPriority(Thread.MAX_PRIORITY);
try {
int i = 0;
restSeconds = seconds;
//Command for each pulse if available (for example, upgrade screen)
while (i < seconds && !this.isCancelled) {
if (this.pulseClock != null && !this.isCancelled) {
this.bot.executeCommand(pulseClock);
}
TimeUnit.SECONDS.sleep(1);
i++;
restSeconds--;
if (this.isCancelled) {
isCancelled = false;
return;
}
}
//Command to end if available.
if (endClock != null && !this.isCancelled) {
this.bot.executeCommand(endClock);
}
isCancelled = false;
} catch (InterruptedException excp) {
ErrorRegister.addErrorLogAndCommand("Error: " + excp);
}
}
public void cancel() {
this.isCancelled = true;
}
public long getRestSeconds() {
return this.restSeconds;
}
}
The problem: sometimes, clock "sleeps" too much time, much more than 1 second. I can be blocked for 15 seconds or more. I setted maximum priority, and the result is the same. Also, it is unpredictable when a larger than expected block will occur.
How can I make sure that it only blocks for a second?
Thank you.
I've been practicing with threads, so I wrote up this timed game where the user needs to guess the correct number (ranges from 1-10). If the user guesses the correct answer in the time limit, the thread stops and the program terminates. It fails to work when the user fails to guess within the time limit. Even though it enters the if-statement after the time limit, it still fails to interrupt the thread completely unless I guess the correct number. I have read other threads but they seem to use ask about the "traditional" guessing game or utilizing Timer. Explanation and/or tips for a suggested solution is also appreciated.
import java.util.*;
import static java.lang.System.out;
import java.io.*;
public class Threading implements Runnable {
private static int num;
private static int k;
public void run() {
try {
Scanner line = new Scanner(System.in);
k = -1;
out.println("Guess!");
while (k != num) {
k = line.nextInt();
if (k != num) {
out.println("Nope");
}
}
}
catch (Exception e) {
out.println("I'm not done!");
}
}
public static void main(String args[]) throws InterruptedException {
num = (int) (Math.random() * 9 + 1);
out.println(num);
Thread t = new Thread(new Threading());
t.start();
long patience = 1000 * 5;
long startTime = System.currentTimeMillis();
while (t.isAlive()) {
t.join(1000);
if (((System.currentTimeMillis() - startTime) > patience) && t.isAlive()) {
out.println("I'm in here!");
t.interrupt();
t.join();
out.println("Times up!");
}
}
}
}
Since one of the comments already points out that the call to nextInt will block I don't think there is a need to go into the details of that.
So for now I'm going to assume you're fine with allowing the user 1 final guess after the timer expires.
The following is the modified code including my comments. I refer to the thread you named t as the "guessing thread".
private static int num;
private static int k;
//Changed variable "line" to "scanner" and made it static so that the
// main method can close it once everything is done.
private static Scanner scanner = new Scanner(System.in);
public void run() {
try {
k = -1;
System.out.println("Guess!");
while (k!=num) {
//Added a check for interrupt, otherwise this thread will never
// end unless the user enters the correct answer.
if(Thread.currentThread().isInterrupted())
return;
k = scanner.nextInt();
if(k != num){
System.out.println("Nope");
}
}
System.out.println("Correct!");
} catch (Exception e) {
System.out.println("I'm not done!");
}
}
public static void main(String args[]) throws InterruptedException {
num = (int) (Math.random() * 9 + 1);
System.out.println(num);
//Declared the guessing thread as final so it can be used inside of
// the TimerTask that is created later.
final Thread t = new Thread(new GuessUntilTimeLimit());
t.start();
long patience = 1000 * 5;
//Use a Timer to enforce your time limit, the TimerTask will execute
// an interrupt of your guessing thread if the thread is still alive
// (it may have died already if user got right answer)
Timer timer = new Timer();
TimerTask task = new TimerTask(){
#Override
public void run() {
if(t.isAlive()){
t.interrupt();
System.out.println("Times up! Enter your final guess now.");
}
}
};
timer.schedule(task, patience);
//Wait for the guessing thread to finish before canceling the timer
t.join();
//By now either the user got the answer or time has run out. Either way
// we need to clean up by canceling the timer.
timer.cancel();
//Added a call to close the scanner, it's always important to release
// resources
scanner.close();
}
Now your main thread schedules a task to execute after patience milliseconds. This task is then responsible for interrupting the "guessing thread". The "guessing thread" will check for interrupt and stop itself when appropriate.
Again, depending on your requirements, you may need to alter the way you accept user input since nextInt will block the thread. For completeness I'm including a link to the question regarding interrupting Scanner.nextLine mentioned in the comments.
I'm trying to limit attempts of a process in a loop to 60 seconds by sleeping for 3,000ms per loop with 20 attempts. Calling Thread.sleep() isn't actually pausing execution in the thread that's running and instead, all 20 attempts happen rapidly in succession.
private void pollWebServiceForToken() {
final int pollInterval = 3000;
new Thread() {
#Override
public void run() {
int attempts = 0;
int maxAttempts = 60;
String token;
do {
token = requestToken(exchangeCode);
if (token.contains(FAILED)) {
try {
Thread.sleep(pollingInterval);
} catch (InterruptedException ex) {
this.currentThread().interrupt();
}
}
attempts++;
} while (token.toLowerCase().contains(FAILED) && attempts < maxAttempts && !cancelled);
}
}.start();
}
Since this is all happening inside of a Vaadin application, I'm assuming the wrong Thread is being put to sleep but I'm not sure how to target a specific thread for sleeping.
Thanks in advance
Are you sure the code inside the if is being run? The condition on the while is different (+toLowerCase). Thread.sleep() always causes the current thread to sleep.
I try to handle the output of different runnables wihtin another thread. First I add all runnables to a set and try to trigger their progress, which is saved into a map toether with the category. The category is the identifier for each runnable. There can exist only one runnable per category.
After that I try to write out the output in a progress bar on the stdout. But it is empty (0%) everytime. The strange thing is, when I am debugging in Eclipse, step by step, the progress bar seems to work correctly. I cannot find the problem, maybe it's some timing problem, or something else.
Can some tell what I am doing wrong?
If someone knows a better way of handling the output of different Threads, please let me know. I am would be happy, definitely.
Thanks in advance for your help.
This is my WriterThread:
public class WriterT extends Thread {
Set<Runnable> my_runnables = new HashSet<Runnable>();
Map<String, Integer> all_runnable_progress = new HashMap<String, Integer>();
public WriterT() {
}
public void add(Runnable r) {
my_runnables.add(r);
}
public void run() {
if(!my_runnables.isEmpty()) {
int progress = 0;
while(true) {
for(Runnable r : my_runnables) {
if(r instanceof Verify_TestRun) {
Verify_TestRun run = (Verify_TestRun)r;
progress = run.get_progress();
all_runnable_progress.put(run.get_category(), progress);
}
}
if(progress <= 100) {
print_progress();
} else {
break;
}
try {
Thread.sleep(150);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private void print_progress() {
StringBuilder str_builder = new StringBuilder();
for(String cat : all_runnable_progress.keySet()) {
int percent = all_runnable_progress.get(cat);
str_builder.append(cat + "\t[");
for(int i = 0; i < 25; i++){
if( i < (percent/4)){
str_builder.append("=");
}else{
str_builder.append(" ");
}
}
str_builder.append("] " + percent + "%" + "\t");
}
System.out.print("\r" + str_builder.toString());
}
}
Updated answer after new information
So if I understand you correctly, you want to go over each test run you are tracking, see if any of them is still running i.e. the progress is less than 100 and print the progress as long as they're not all finished.
First, you need to consider what Stephen C said in his answer - you (probably) want to sum up the progress values of each of the test runs. Then, check if the sum comes out to less than 100 for each test run. If it does, at least 1 test run is still in progress and you print progress and stay in your loop. If you find that your sum comes out to exactly 100 for each test run, then you're all done. You print progress one final time to update the output to reflect 100% for each and then break from the loop.
Here is my suggested implementation that makes minor changes to your code:
public void run() {
if(!my_runnables.isEmpty()) {
int progress = 0;
while(true) {
for(Runnable r : my_runnables) {
if(r instanceof Verify_TestRun) {
Verify_TestRun run = (Verify_TestRun)r;
//change #1 - sum up the progress value of each test
progress += run.get_progress();
all_runnable_progress.put(run.get_category(), progress);
}
}
//change #2 - break when all done
if(progress < (100 * my_runnables.size()) ) {
//check if tests are still running i.e. there are test runs with progress < 100
print_progress();
} else {
//otherwise print one last status (to update all status' to 100%) before stopping the loop
print_progress();
break;
}
try {
Thread.sleep(150);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Shouldn't progress be checked within the for loop? What you're doing right now is iterating over all your Runnables and setting progress to the progress value and adding it to the map. But then you immediately move on to the next Runnable. The net result is that the value of progress once you leave the loop is the value of the last Runnable you handled.
I think that this might be the problem line:
progress = run.get_progress();
Given the context, progress will end up as the last value returned by a Verify_RunTest, but I suspect you mean it to be the sum of the values.
(BTW - Verify_RunTest is bad style. It should be VerifyRunTest.)
In the code, the variable timer would specify the duration after which to end the while loop, 60 sec for example.
while(timer) {
//run
//terminate after 60 sec
}
long start = System.currentTimeMillis();
long end = start + 60*1000; // 60 seconds * 1000 ms/sec
while (System.currentTimeMillis() < end)
{
// run
}
you should try the new Java Executor Services.
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html
With this you don't need to program the loop the time measuring by yourself.
public class Starter {
public static void main(final String[] args) {
final ExecutorService service = Executors.newSingleThreadExecutor();
try {
final Future<Object> f = service.submit(() -> {
// Do you long running calculation here
Thread.sleep(1337); // Simulate some delay
return "42";
});
System.out.println(f.get(1, TimeUnit.SECONDS));
} catch (final TimeoutException e) {
System.err.println("Calculation took to long");
} catch (final Exception e) {
throw new RuntimeException(e);
} finally {
service.shutdown();
}
}
}
If you can't go over your time limit (it's a hard limit) then a thread is your best bet. You can use a loop to terminate the thread once you get to the time threshold. Whatever is going on in that thread at the time can be interrupted, allowing calculations to stop almost instantly. Here is an example:
Thread t = new Thread(myRunnable); // myRunnable does your calculations
long startTime = System.currentTimeMillis();
long endTime = startTime + 60000L;
t.start(); // Kick off calculations
while (System.currentTimeMillis() < endTime) {
// Still within time theshold, wait a little longer
try {
Thread.sleep(500L); // Sleep 1/2 second
} catch (InterruptedException e) {
// Someone woke us up during sleep, that's OK
}
}
t.interrupt(); // Tell the thread to stop
t.join(); // Wait for the thread to cleanup and finish
That will give you resolution to about 1/2 second. By polling more often in the while loop, you can get that down.
Your runnable's run would look something like this:
public void run() {
while (true) {
try {
// Long running work
calculateMassOfUniverse();
} catch (InterruptedException e) {
// We were signaled, clean things up
cleanupStuff();
break; // Leave the loop, thread will exit
}
}
Update based on Dmitri's answer
Dmitri pointed out TimerTask, which would let you avoid the loop. You could just do the join call and the TimerTask you setup would take care of interrupting the thread. This would let you get more exact resolution without having to poll in a loop.
Depends on what the while loop is doing. If there is a chance that it will block for a long time, use TimerTask to schedule a task to set a stopExecution flag, and also .interrupt() your thread.
With just a time condition in the loop, it could sit there forever waiting for input or a lock (then again, may not be a problem for you).