Java Thread.sleep inquiry - java

So I was wondering if there was anyway I could implement this code so that it pauses on each loop iteration. Currently, when I run the code, the program will stop for n seconds (n being the amount of loop iterations) and then display everything at once. However, I wish for it to display one item, wait one second and display the next item. I hope this is clear.
while(x > 0 || y > 0){
Try{
Thread.sleep(1000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
// Print x and y
//Change x and y vals
}
}

First, don't suppress InterruptedException. If there's nothing to be done about it, simply don't catch it at all, or convert it into a RuntimeException e.g.
throw new RuntimeException(ie);
Second, it sounds like you're describing a flushing problem, which can be addressed by adding calls to:
System.out.flush();
After you print your values. As mentioned in the linked question however, System.out and System.err auto-flush whenever a new line is printed; are you not printing to stdout, or not printing new lines?
You should have a Thread.sleep() call wherever you need the program to pause, so if you need to pause between printing x and y, add another Thread.sleep() between them.

Suggestion: separate the thread sleep in a method to do the job without rewriting all this code.
Suggestion 2: search aroung if thread sleep is the best solution for you
Try this:
public void waitSeconds(int seconds){
try{
Thread.sleep(seconds*1000l);
} catch(Exception e) {
e.printStackTrace(); //ugly but enough to explain
};
}
public void yourMethod(){
while(x > 0 || y > 0){
waitSeconds(1);
print x
waitSeconds(1);
print y
//Change x and y vals
}
}

It's really strange. Try this way:
while(x > 0 || y > 0) {
// Print old values
// Change your x and y
// Print new values
try {
TimeUnit.SECONDS.sleep(y);
} catch(InterruptedException ex) {}
}

Related

Random for-loop in Java?

I have 25 batch jobs that are executed constantly, that is, when number 25 is finished, 1 is immediately started.
These batch jobs are started using an URL that contains the value 1 to 25. Basically, I use a for loop from 1 to 25 where I, in each round, call en URL with the current value of i, http://batchjobserver/1, http://batchjobserver/2 and so on.
The problem is that some of these batch jobs are a bit unstable and sometimes crashes which causes the for-loop to restart at 1. As a consequence, batch job 1 is run every time the loop is initiated while 25 runs much less frequently.
I like my current solution because it is so simple (in pseudo code)
for (i=1; i < 26; i++) {
getURL ("http://batchjob/" + Integer.toString(i));
}
However, I would like I to be a random number between 1 and 25 so that, in case something crashes, all the batch jobs, in the long run, are run approximately the same number of times.
Is there some nice hack/algorithm that allows me to achieve this?
Other requirements:
The number 25 changes frequently
This is not an absolut requirement but it would be nice one batch job wasn't run again until all other all other jobs have been attempted once. This doesn't mean that they have to "wait" 25 loops before they can run again, instead - if job 8 is executed in the 25th loop (the last loop of the first "set" of loops), the 26th loop (the first loop in the second set of loops) can be 8 as well.
Randomness has another advantage: it is desirable if the execution of these jobs looks a bit manual.
To handle errors, you should use a try-catch statement. It should look something like this:
for(int i = 1, i<26, i++){
try{
getURL();
}
catch (Exception e){
System.out.print(e);
}
}
This is a very basic example of what can be done. This will, however, only skip the failed attempts, print the error, and continue to the next iteration of the loop.
There are two parts of your requirement:
Randomness: For this, you can use Random#nextInt.
Skip the problematic call and continue with the remaining ones: For this, you can use a try-catch block.
Code:
Random random = new Random();
for (i = 1; i < 26; i++) {
try {
getURL ("http://batchjob/" + Integer.toString(random.nextInt(25) + 1));
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
Note: random.nextInt(25) returns an int value from 0 to 24 and thus, when 1 is added to it, the range becomes 1 to 25.
You could use a set and start randomizing numbers in the range of your batches, while doing this you will be tracking which batch you already passed by adding them to the set, something like this:
int numberOfBatches = 26;
Set<Integer> set = new HashSet<>();
List<Integer> failedBatches = new ArrayList<>();
Random random = new Random();
while(set.size() <= numberOfBatches)
{
int ran = random.nextInt(numberOfBatches) + 1;
if(set.contains(ran)) continue;
set.add(ran);
try
{
getURL ("http://batchjob/" + Integer.toString(ran));
} catch (Exception e)
{
failedBatches.add(ran);
}
}
As an extra, you can save which batches failed
The following is an example of a single-threaded, infinite looping (also colled Round-robin) scheduler with simple retry capabilities. I called "scrape" the routine that calls your batch job (scraping means indexing a website contents):
public static void main(String... args) throws Exception {
Runnable[] jobs = new Runnable[]{
() -> scrape("https://www.stackoverfow.com"),
() -> scrape("https://www.github.com"),
() -> scrape("https://www.facebook.com"),
() -> scrape("https://www.twitter.com"),
() -> scrape("https://www.wikipedia.org"),
};
for (int i = 0; true; i++) {
int remainingAttempts = 3;
while (remainingAttempts > 0) {
try {
jobs[i % jobs.length].run();
break;
} catch (Throwable err) {
err.printStackTrace();
remainingAttempts--;
}
}
}
}
private static void scrape(String website) {
System.out.printf("Doing my job against %s%n", website);
try {
Thread.sleep(100); // Simulate network work
} catch (InterruptedException e) {
throw new RuntimeException("Requested interruption");
}
if (Math.random() > 0.5) { // Simulate network failure
throw new RuntimeException("Ooops! I'm a random error");
}
}
You may want to add multi-thread capabilities (that is achieved by simply adding an ExecutorService guarded by a Semaphore) and some retry logic (for example only for certain type of errors and with a exponential backoff).

Selenium and Java: While loop not working as expected

I have a challenge with automating a click action and I'm struggling to understand what's wrong with the logic in my solution.
My challenge is that I need to click one of a number of different radio buttons.
Each radio button has an id of "r" + a_number.
I don't know, for any given test, what the available "r" + a_number options there will be, so I wrote this while loop, which is intended to click the first available radio button:
int counter = 0;
while(true) {
counter++;
try {
driver.findElement(By.id("r" + counter)).click();
} catch (NoSuchElementException e) {
continue;
}
break;
}
This isn't working as intended - could someone help me understand what's wrong?
Note: I'm a novice with Java
Update
My aim is to click the first existing radio button, so the while loop increments the counter var, let's say r=1, then attempts to click a radio button with id "r1". If there is no such element with id "r1", a NoSuchElementException is thrown, in which case the current while loop iteration should stop and start the next iteration (r = 2, try to click element "r2", if does not exist, start next while loop cycle).
Suppose we get to element "r20" and this element does in fact exist, then the button should be clicked, the exception is not thrown and so the while loop continues and hits the break command, and the while loop is terminated.
The current behaviour, however, is that the exception does not get handled even when the element does not exist, the while loop terminates, but nothing has been clicked.`
There are two issues with the code:
Loop running only once- You are breaking the loop using break statement, after the first iteration itself.
No exception thrown- You are not logging the exception. You are only executing a 'continue' statement in the catch block. You do not need the statement because the loop will go to next iteration anyway (well after you remove the break statement).
You should use this code:
int counter = 0;
boolean foundElement = false;
while(!foundElement) {
counter++;
try {
driver.findElement(By.id("r" + counter)).click();
foundElement = true;
} catch (NoSuchElementException e) {
//assuming you want to log exception. Otherwise you can leave the catch block empty.
System.out.println(e);
}
}
Not sure and may need little more information however, I would do it little differently
int counter = 0;
boolean ifNotFound = true;
while(ifNotFound) {
counter++;
try {
driver.findElement(By.id("r" + counter)).click();
ifNotFound = false;
} catch (NoSuchElementException e) {
System.out.println("exception caught");
}
}
I am just trying to click and if it is successful then will set the while loop to false and it will break.
It may be possible that the exception you are catching is not the one is being thrown so you may try to change it to generic Exception and if that works then you can catch more specific one or more than one if you need to.
Please use this:
int counter = 0;
while(true) {
counter++;
boolean elementFound = false;
try {
driver.findElement(By.id("r" + counter)).click();
elementFound = true;
} catch (NoSuchElementException e) {
continue;
}
if (elementFound){
break;
}
}

Break if check in thread java

My program is coded in Java. I have an IF() check in run() method (in a Thread). In the IF check, if the condition is satisfied, it shows a Window dialog (using JOptionPane.showMessageDialog) with OK button. However, it shows infinitely. When I click OK it pops up again and again. How can I end the if check after the user click OK. Or when the condition is met, it only shows once ?
This is my method()
public void danhHoiWumpus()
{
if ((GameScreen.bg[x[0] + 1][y[0]] == 2) || (GameScreen.bg[x[0] + 2][y[0]] == 2) || (GameScreen.bg[x[0] + 3][y[0]] == 2) || (GameScreen.bg[x[0]][y[0]+1] == 2) || (GameScreen.bg[x[0]][y[0]+2] == 2) || (GameScreen.bg[x[0]][y[0]+3] == 2))
{
JOptionPane.showMessageDialog(this, "Có mùi wumpus ! \n Bạn được học bổng 40%");
}
}
This is my run() method
public void run()
{
while(true)
{
hunter.update();
hunter.danhHoiWumpus();
// i++;
repaint();
// System.out.println("Gia tri cua y la " +i);
try {
thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The idea of this action is. When the RED square is going near the YELLOW square, it will pop up a dialog "I smell Wumpus". When the user click OK. They will choose to shot the wumpus (I will do this later).
And here is my full source code (for reference):
https://www.mediafire.com/?wkp6hyq32nq23mp
Thank you in advance.
Your code is executing in an infinite while loop
while(true)
// I am infinite
}
The term you are looking for is hit detection. There are a myriad of ways to achieve it. Look up hit detection in Java for some pointers.
What you have isn't necessarily wrong though.
while (true) // I'm not always bad!
is used in a lot of applications. However, while your code isn't completely posted, I don't see anywhere you break from this. You may be interested in the
java.util.Timer
and the
java.util.TimerTask
Both of those have wide application in Java game development
Your sleep time is too low (20 nanoseconds). Increase the time, otherwise it will happen too quick for you to understand it.
You are potentially triggering this if condition many many times.
You need some 'rising edge trigger' logic in order to only trigger when the new value goes from false to true, instead of triggering whenever it's true.
currentValue = bigLongLogicCheck;
if(!oldvalue&&currentValue) {alert()}
oldvalue = currentValue

Java: Running potentially blocking code

I am developing a small game, (Java, LibGdx) where the player fills cloze-style functions with predefined lines of code. The game would then compile the code and run a small test suite to verify that the function does the stuff it is supposed to.
Compiling and running the code already works, but I am faced with the problem of detecting infinite loops. Consider the following function:
// should compute the sum of [1 .. n]
public int foo(int n) {
int i = 0;
while (n > 0) {
i += n;
// this is the place where the player inserts one of many predefined lines of code
// the right one would be: n--;
// but the player could also insert something silly like: i++;
}
return i;
}
Please note that the functions actually used may be more complex and in general it is not possible to make sure that there cannot be any infinite loops.
Currently I am running the small test suite (provided for every function) in a Thread using an ExecutorService, setting a timeout to abort waiting in case the thread is stuck. The problem with this is, that the threads stuck in an endless loop will run forever in the background, which of course will at some point have a considerable impact on game performance.
// TestClass is the compiled class containing the function above and the corresponding test suite
Callable<Boolean> task = new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
// call the test suite
return new TestClass().test();
}
};
Future<Boolean> future = executorService.submit(task);
try {
Boolean result = future.get(100, TimeUnit.MILLISECONDS);
System.out.println("result: " + (result == null ? "null" : result.toString()));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
future.cancel(true);
}
My question is now: How can I gracefully end the threads that accidentally spin inside an endless loop?
*EDIT To clarify why in this case, preventing infinite loops is not possible/feasable: The functions, their test suite and the lines to fill the gaps are loaded from disk. There will be hundrets of functions with at least two lines of code that could be inserted. The player can drag any line into any gap. The effort needed to make sure no combination of function gap/code line produces something that loops infinitely or even runs longer than the timeout grows exponentially with the number of functions. This quickly gets to the point where nobody has the time to check all of these combinations manually. Also, in general, determining, whether a function will finish in time is pretty much impossible because of the halting problem.
There is no such thing as "graceful termination" of a thread inside the same process. The terminated thread can leave inconsistent shared-memory state behind it.
You can either organize things so that each task is started in its own JVM, or make do with forceful termination using the deprecated Thread.stop() method.
Another option is inserting a check into the generated code, but this would require much more effort to implement properly.
The right way is to change the design and avoids never ending loops.
For the time being, inside your loop you could check if the thread is interrupted some way by: isInterrupted() or even isAlive().
And if it is you just exit.
It is not normal to have a never ending loop if it not wanted.
To solve the problem You can add a counter in the loop and if you reach a limit you can exit.
int counter = 0;
while (n > 0) {
counter++;
if (counter > THRESHOLD) {
break;
}
i += n;
// this is the place where the player inserts one of many predefined lines of code
// the right one would be: n--;
// but the player could also insert something silly like: i++;
}

Filing labels with color

I have Grid of labels (size n*n) and I want to fill with color its irregular part. I wrote a method
private void fill(int j){
while(board[j].getName().equals("s")){
board[j].setBackground(Color.yellow);
try{
fill(j-1);
} catch (ArrayIndexOutOfBoundsException e){}
try{
fill(j+1);
} catch (ArrayIndexOutOfBoundsException e){}
try{
fill(j+n);
} catch (ArrayIndexOutOfBoundsException e){}
try{
fill(j-n);
} catch (ArrayIndexOutOfBoundsException e){}
}
}
and I'm still getting StackOverflowError. I'm not using big parts (my n is max 20), I've tried to replace while with if, but didn't work too. Is it too big for a stack or might be there infinite loop? How I can fix that?
Lets say that for some reason for
j and j-1 condition in while will are satisfied,
for rest values like j-2 not
So if you invoke fill(j) program will
test while condition for j (pass)
enter while loop
setBackground for j
invoke fill(j-1);.
Now before program will invoke fill(j+1), program will have to finish fill(j-1) so flow of control will be moved to fill(j-1) level and program will
test while condition for j-1 (pass)
you enter while loop
setBackground for j-1
invoke fill((j-1)-1); in other words fill(j-2).
And again before fill((j-1)+1) flow of control will be moved to fill(j-2) so program will
test while condition for j-2 (fail)
program cant enter loop so will return return from fill(j-2)
invoke fill((j-1)+1) which is the same as fill(j)
So your application will try to repeat the same scenario, but this time on different stack level which will lead to StackOverwlow.
To prevent this situation maybe change condition to also test if you already been at this position, like
while(board[j].getName().equals("s") && board[j].getBackground() != Color.yellow)
You can/should also change while to if.
board[j].setName("bgSet")
after
board[j].setBackground(Color.yellow)
this might solve the problem, otherwise your while is always true.

Categories