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.
Related
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!
I want to run java code for a certain duration ,say 16 hours! I have a java code that runs for approximately an hour.I want this to run repeatedly for 16 hours. So I have a parameter that is passed by the user through Jenkins ! I access this value using
System.getenv("Duration");
Now, I want to exit the execution after the specified time. So suppose the user selected 16, the script should run for 16 hours and then exit.
Accepting input from Jenkins user as shown in the image
I saw some other questions, but most of them were dealing with timers for either few seconds or few minutes. I need an efficient solution. Thanks :)
FYI - Environment - Jenkins+TestNG+Maven+Java
EDIT :
long start = System.currentTimeMillis();
long end = start + durationInHours*60*60*1000;
while (System.currentTimeMillis() < end)
{
//My code here runs for approx. 50 mins!
}
Now suppose the user chooses the value 3 hours, I want the while loop to exit after 3 hours. But this does not happen as it has not yet completed 3 hours when checking the while condition.So it enters the while condition even the 4th time(since time elapsed is 150 mins which is less than 180 mins) it ends after 3 hours ten mins.
How to make it exit the while loop as soon as 180 mins is reached ?
P.S - I could do the math first,( iterations =durationFromUser/codeDuration) and then run a for loop, but I don't want to do this as my script length may vary.
EDIT 2:
boolean alive = true;
Timer timer = new Timer();
#Test() //Annotation from TestNG
public void public void jenkinsEntryPoint()
{
String duration = System.getenv("Duration");
int durationInHours=Integer.parseInt(duration);
long end = System.currentTimeMillis() + durationInHours*60*60*1000;
TimerTask task = new TimerTask() {
public void run() {
alive = false;
};
timer.schedule(task, end);
while (alive) {
//My code here runs for approx. 50 mins!
function1();
}
}
void function1() {
function2();
}
private void function2() {
for(i=0;i<8;i++)
{
while(alive)
{
//long running code
sleep(1000);
//Some more code
sleep(2000);
//Some more code
//Suppose time elapses here, I want it to quit
//But its continuing to execute
.
.
.
.
}
}
}
The while condition will only be evaluated between script invocations (as you've seen). You will have to break out of your long running from inside of it.
I would typically use a Timer to set a "global" boolean that you would check from inside the loops in your long running code.
Something like this. Notice checks against 'alive' would have to be in all you long loops...
boolean alive = true;
Timer timer = new Timer();
public void jenkinsEntryPoint()
long end = System.currentTimeMillis() + durationInHours*60*60*1000;
TimerTask task = new TimerTask() {
public void run() {
alive = false;
};
timer.schedule(task, end);
while (alive) {
//My code here runs for approx. 50 mins!
yourLongRunningCode()
}
public void yourLongRunningCode() {
while (alive) {
doStuff();
}
}
I tried ScheduledThreadPoolExecutor and it worked!
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
exec.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println("Time's Up According To ScheduledThreadPool");
alive = false;
}
}, durationInHours, 1, TimeUnit.HOURS);
This function will be executed after "durationInHours".
Thanks #TedBigham :)
Hi I am trying to create a simple 10 second count down timer for my Libgdx game but it keeps printing 0.0 remaining. When my screen starts I create a gotime variable to hold the initial start time. I then set a target time variable targettime by adding 10000 to gotime. Then surely it is just a matter of subtracting the targettime with current time but this isn't working. I believe it is because for some reason my gotime and targettime are printing out the same timestamp in the logcat with a strange E number like the following 1.3980063E12. I am using Time.Utils.millis() to get times. Thanks.
gotime=TimeUtils.millis();
targettime=gotime+10000;
timeleft=targettime-TimeUtils.millis();
Try something like this
boolean TimerRunning = true;
int Timer = 10;
new Thread(new Runnable() {
public void run() {
while(TimerRunning == true) {
Thread.sleep(1000);
if(Timer == 0) {
TimerRunning = false;
}
else {
Timer = Timer - 1;
}
}
}).start();
And then use A method too get the Variable Timer! and you be done!
The object is supposed to change modes (movement algorithm) every 5 seconds. I first tried with a while loop but the loop was iterating way too fast. Then I added Thread.sleep(5000) but still my object moves only in one algorithm (scatterMode). Here is the algorithm:
//LEVEL 1
//scatter for 7s
//chase for 20s
//scatter for 7s
//chase for 20s
//scatter for 5s
//chase for 20s
//scatter for 5s
//chase indefinite
And here is the code. The constructor and variable declarations are at the bottom if you need to see them.
public void updateMode() throws InterruptedException {
while(ghostalive){
if(seconds<7){
Thread.sleep(100);
mode = scatterMode;
}
if(7<seconds && seconds<27){
Thread.sleep(5000);
mode = chaseMode;
}
if(27<seconds && seconds<34){
Thread.sleep(5000);
mode = scatterMode;
}
if(34<seconds && seconds<54) {
Thread.sleep(5000);
mode = chaseMode;
}
if(54<seconds && seconds>59) {
mode = scatterMode;
}
if(59< seconds && seconds<79){
mode = chaseMode;
}
if(seconds>84){
mode = scatterMode;
ghostalive=false;
}
seconds++;
ghostalive=false;
}
}
private int seconds=0;
private boolean ghostalive=true;
protected static final int chaseMode = 0;
protected static final int scatterMode = 1;
static int mode = scatterMode; //initially ghost start in scatterMode
public Ghost(int x, int y, Maze maze) throws InterruptedException{
super(x, y, maze);
futureDirection = 0;
timer = 0;
updateMode();
//chaseMode = false;
//frightenedMode = false;
}
public static int getMode(){
return mode;
}
Your sleep pattern is mixture of milliseconds and several seconds, but you are expecting to count seconds.
Try something like this:
while(ghostalive){
if(seconds<7){
mode = scatterMode;
}
if(7<seconds && seconds<27){
mode = chaseMode;
}
if(27<seconds && seconds<34){
mode = scatterMode;
}
if(34<seconds && seconds<54) {
mode = chaseMode;
}
if(54<seconds && seconds>59) {
mode = scatterMode;
}
if(59< seconds && seconds<79){
mode = chaseMode;
}
if(seconds>84){
mode = scatterMode;
ghostalive=false;
}
seconds++;
Thread.Sleep(1000);//Sleep for one second only
//ghostalive=false; // Should this be here? Ghost is set to not alive after each loop?
}
I have moved the sleep after the if statements so that it is consistent in each loop.
I think you should not rely on Sleep for measuring time because it can behave differently everytime you run it. Thread can goto sleep for more than the mentioned time. Sleep only pauses current thread for specific time. It does not guarantees that this thread will start executing again after same time.
Do NOT invoke updateMode from the constructor.
Instead, start a new thread.
As of now, probably the following happens: your Ghost is creates, goes through all of his stages before the constructor is complete. Then when your main program starts, your ghost is ghostalive=false and in scatterMode already.
For debugging, put in a lot of Loggin statements. It's best to use the logging APIs, but many beginners prefer System.out.println. It is a good practise to just print what you are doing - i.e. which mode you set the ghost to.
When you then also add game timer things, you should easily see that the ghost first goes through all of his states, before your actual game even started (i.e. a "game has started" logging is also a must.
Logging is not at all more difficult than printing.
// for each class, add such a line:
private static final LOG = java.util.logging.Logger.getLogger("packagename.classname");
static {
// Configure the active logging level manually
// For larger projects, use a .properties file!
LOG.setLevel(java.util.logging.Level.ALL);
}
// inside of appropriate methods, use
if (LOG.isLoggable(Level.DEBUG)) {
LOG.log(Level.DEBUG, "My ghost is now frightened.");
}
The if statement is important. It can be optimized well by hotspot, so that if logging is disabled, the logging statements come at next to no cost.
The good thing is that you can turn on and off these statements easily. While System.out.println you have to manually remove and readd to your code.
When seconds is exactly 7 or 34 or 54,..., there is no condition to handle these cases. It just doesn't enter in any of the if statements.
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.)