When executing a while loop, does java constantly check if the parameter(s) are true? For example if a while loop is
while(k=7) {
Thread.sleep(5000);
}
but during the 5 seconds another thread changes k to 8, would the loop continue waiting or exit immediately?
No, it will only check when the execution path takes it there. Thus, it will check every 5 seconds in your example.
If you wanted to be notified immediately, you would have to use wait(), notify(), or some other synchronization method.
Here is an example
No. Even if k were volatile (or, worse, changed from another thread without you making it volatile; bad idea) or an object whose properties could change via the methods called inside the loop, it will only be checked at the end of the loop body, deciding to repeat the body or continue past the loop.
You can break out of the loop by interrupting the thread and having the catch outside the loop, or with an internal check and break.
The condition is checked once at the start and, if the loop is entered, once after the execution of the body on each iteration. So no, it will not exit immediately, even if k is altered while the body is being executed.
Oh, and you probably meant k == 7 (recall that == compares while = assigns). Some will even write 7 == k to avoid potentially making this mistake.
This doesn't really have much to do with threads. For instance, consider:
int k = 7;
while (k == 7) {
k = 8;
System.out.println("here!");
}
here!
Notice how the body is still fully executed even though k is immediately changed to a value that no longer satisfies the loop condition.
Related
I have a program I need to implement that has the following code:
for (int n = 1024; true; n+=n)
I cannot find any other examples of java loops having such a format. What does this mean? I've tried to research it, but I don't even know what to search for - it's totally foreign to me.
The basic for statement is described in the language spec:
for ( [ForInit] ; [Expression] ; [ForUpdate] ) Statement
You are asking about the case when Expression is true. (The square brackets above mean it is optional).
The meaning of that is described just below, in Sec 14.14.1.2:
If the Expression is not present, or it is present and the value resulting from its evaluation (including any possible unboxing) is true, then the contained Statement is executed.
...
If the Expression is present and the value resulting from its evaluation (including any possible unboxing) is false, no further action is taken and the forstatement completes normally.
So, Expression is present, and evaluates to true (because true evaluates to true). Hence, Statement is executed, and will continue to be executed because Expression remains true.
As such, it is an infinite loop (unless there is a break, return, throw or System.exit inside the loop).
Why you dont use another loop? Use for example do-while instead of
for (int n = 1024; true; n+=n)
You can make a work around with:
int n=1024;
do{
//your code
n+=n;
}while(condition==false);
When it comes to counting, should a do-while loop be used, or a for loop? Because this:
class Main {
public static void main(String[] args) {
int times = 1;
do {
System.out.println("I have printed " + times + " times.");
times++;
} while (times < 6);
}
}
Seems to do the exact same thing as this:
class Main {
public static void main(String[] args) {
for (int times = 1; times < 6; times++) {
System.out.println("I have printed " + times + " times.");
}
}
}
Is it a difference in speed? Preference? Situation? Personal quirks? Some kind of "Java social taboo"? I have no idea. Either seem to be able to be used for effective counting, just that one takes a lot more. And both print the exact same thing.
System.out.println("Many thanks!!");
You're right, these do the same thing (except one starts counting at 0 and the other at 1, but that's just an implementation detail). If your program knows in advance (before the loop starts) how many times you want the loop to iterate, most Java developers will tell you to go with a for loop. That's what it's designed for.
A while loop or do while loop is better suited for situations where you're looking for a specific value or condition before you exit the loop. (Something like count >= 10 or userInput.equals("N"). Anything that evaluates to a boolean True/False value.)
When faced with these kind of dilemmas, aim for readability and familiarity. You should not concern yourself with micro-optimizations. Focus on readability and clearly conveying you intent. Do as other do in similar situation.
Like #Bill-The-Lizard said, while loop suggests to the reader of your code that you opted for it, because you're not counting, but repeating until a condition is met. At least once - otherwise you'd have chosen while(...){ } loop.
In other words, for, do {} while() and while() { } generally work the same. But one may better convey you intent in your particular piece of logic.
I think it's more of a readability and syntactic sugar. This while condition
while (condition)
can also be written as
for (; condition; )
but obviously the first one looks lot better and is more readable.
It depends on the programmer's choice when to use for loop or do while loop but the general practice followed by most of the programmers is
For loop
When you know that the loop will execute a predefined number of times(general practice since you can also use for(;true;) which loops forever).
For example a loop which runs 10 times or n number of times where n is a variable
for(int i = 0; i < n; i++) {
//Do something
}
While loop
When you know that the loop should terminate after the evaluation of a specific condition as true or else you want the loop to run forever (like while(true)) and check the break conditions inside the while loop.
Also the while loop is preferred when you can't figure out the conditions in the first place and start with while(true) but once you write code inside the loop you get good understanding of what's happening and get the idea about which conditions to check thus when to exit the loop.
For example
while(x != 0) {
//Do something;
x--;
}
while(true) {
// some code to execute on which the condition depends
if(condition is true) {
break;
}
}
Do while loop
Do while loop is similar to the while loop but with a small difference. That is it allows the first iteration to happen without checking the condition(specified in the while statement, but you can still evaluate the condition inside the block(curly braces)).
By convention most Java developers use for loops. Effective Java recommends for loops instead of while loops because the loop variable can use a tighter scope which reduces bugs. http://www.corejavaguru.com/effective-java/items/45
Recent versions of Java also allow the following
IntStream.range(0, 6).forEach(
i -> System.out.println("I have printed " + i + " times.")
);
Beyond personal preferences, this one has the advantage that the index is maintained by the runtime and there is no need for the programmer to ++i
This question already has answers here:
Is it a bad practice to use break in a for loop? [closed]
(19 answers)
Closed 7 years ago.
I am just curious as I have been using break statements a lot, but apparently I was told that is bad practice. Obviously logically if something is met it could terminate as well. I just want to know if there is something else besides break.
That would break out of the for loop. In fact break only makes sense when talking about loops, since they break from the loop entirely, while continue only goes to the next iteration
try this:
for(int i= 0; i<MAX; i++){
if(listEmpt[i] == null){
listEmpt[i] = employeeObj;
i=MAX;
}
but I see no problem with using breaks. There will always be circumstances where you want to stop processing a loop, and using a break; makes much more sense (and makes it more readable!) than setting your loop counter up to a value that would make your loop stop at the next iteration.
you can also use labeled breaks that can break out of outer loops (and arbitrary code blocks)
looplbl: for(int i=;i<;i++){
if (i == temp)
// do something
else {
temp = i;
break looplbl;
}
}
An unlabelled break only breaks out of the enclosing switch, for, while or do-while construct. It does not take if statements into account.
See for more details.
With regards about the use of break, you could check here.
Since while loops were not covered (another form of looping which I personally use a lot), you could look towards settings conditions for the loops such as
boolean flag = true;
while (flag) {
//do something that modifies the below condition
if (condition) {
//do something
flag = false;
}
}
Upon which the loop will terminate when the condition equates to true, since that sets the flag to false.
If you simply return from within your loop, that should be sufficient. Most people think you have to terminate the loop, but this is not the case.
Also, see this answer too.
I wrote a method that should be repeated 1000 times and the method is again another loop (like a nested loop).Since the running time was not reasonable I decided to write a thread to run it faster. Here is the method:
public class NewClass implements Runnable {
#Override
public void run() {
for (int j = 0; j < 50; j++) {
System.out.println(i+","+j);
/*
*
* my method
*/
}
}
}
and here is the way the main class calls it:
for (int i = 0; i < 1000; i++) {
NewClass myMethod = new NewClass();
Thread thread = new Thread(myMethod);
thread.start();
}
the problem is that when I run it, the thread skips the first iteration (when i=0) in the main class and then in the next iterations, it skips some iterations of inner loop (myMethod). Here is the result of println:
1,0
1,1
2,0
2,1
3,0
3,1
3,2
...
3,22
4,0
...
clearly it skips i=0 and for other iterations it cannot finish it. I'm sure the problem is not in the body of method. I run it several times without thread. It is the first time I write thread and I think the problem is in thread.
Your loop index for i starts from 1 (I'm guessing? It's not even clear why it's in scope), so it's unsurprising that i = 0 does not occur. Similarly, I think you're confused about the printing order, which need not be deterministic. It may be printing the output interspersed with output from other threads. This is normal and expected. I think the code is behaving correctly, it might just not be doing what you want.
I noticed you edited your code. This doesn't really bode well for anybody being able to help you diagnose whatever unexpected behavior you're seeing.
It just so happens that no thread calls the print function while i is zero. You don't compel this ordering, so it may or may not happen in that order. Either of these things can happen.
i is zero
A thread is created.
The thread prints the value of i.
i is incremented.
Or
i is zero
A thread is created.
i is incremented.
The thread prints the value of i.
Your code doesn't enforce either ordering, so it can happen either way. You only have guaranteed ordering between threads when something in your code guarantees such ordering.
clearly it skips i=0 and for other iterations it cannot finish it. I'm sure the problem is not in the body of method. I run it several times without thread. It is the first time I write thread and I think the problem is in thread.
There are 2 reason why this could be happeneing.
You seem to be printing out i which is a shared between threads without any memory synchronization. See the tutorial on memory synchronization. Each processor has internal cached memory so even though i is being modified in the main memory, the processor cache may still see the old value.
You also are probably seeing a race condition. What is happening is that the first two threads (0 and 1) are started before either of their run() methods actually being called. So when they both run and print out 1 because that is what i's value is at the time.
Because of either or both of these reasons, if you run your application 10 times you should see vastly different output.
If you want i to be shared then you could turn it into an AtomicInteger and do something like:
final AtomicInteger i = new AtomicInteger(0);
...
// replacement for your for loop
i.set(0);
while (true) {
if (i.incrementAndGet() >= 1000 {
break;
}
...
}
...
// inside the thread you would print
System.out.println(i + "," + j);
But this mechanism does not solve the race condition. Even better would be to pass in the i value to the NewClass constructor:
private int i;
public NetClass(int i) {
this.i = i;
}
...
Then when you create the instances you do:
NewClass myMethod = new NewClass(i);
1.
for (int i = 0; (boolean)true; i++) {
}
2.
for (int i = 0; (boolean)false; i++) {
}
3.
boolean t=false;
for (int i = 0; t; i++) {
}
The first for loop compiles & runs, but the second for loop compilation fails with error. It says Unreachable Statement. And the third for loop compiles & runs.
The first loop is infinite loop. Since the condition is always true, and will always be satisfied.
It's like writing:
int i=0;
while(true)
i++;
As you can see, the condition is always true and nothing changes this true.
The second loop is Unreachable code since the piece of code below this loop will never be reached (false is always false and you never change it). So it's redundant.
See Chapter 14.21. Unreachable Statements
Since Java knows that the programmer is human :) it notifies you about this to prevent mistakes.
Note that while(false) or the second loop you have differ from if(false)... since while(false) (or the loop you have) doesn't make sense because the code below it will no be execute. Not like if(false) that might have else, so the compiler doesn't complain about it in this case.
Regarding the OP update:
In the third case there will be no compilation error since the false value is assigned to the variable and in this case, the variable can be re-assigned to have true value in it. So the compiler doesn't arise an error.
Note that if the variable is declared as final then the compiler will arise an error since this variable can be never assigned to a new value, thus the code below the for loop will be unreachable.
for (int i = 0; <This_has_to_be_true>; i++)
The second part of the for loop has to be true for the loop to execute. Since you're manually setting it to be always fase, the loop will never run, hence the code inside it is unreachable.
The compiler is telling you the code inside the second loop (even if empty) will never be reached and executed, because the condition is always false.
BTW, why are you trying to do this anyway?
In the second for loop, the condition is always false so the for block (even if is empty) will never be executed (it is unreacheable).
Like in this case :
if (false) {
}