Passing value from inside while loop to different class - java

So let's say I have a main class with a while loop:
public class Main {
public static void main(String[] args) throws InterruptedException {
int one = 1;
int counter = 0;
while (one<100){
Thread.sleep(1000);
counter += 1;
Function.Move();
one++;
}
The counter variable in this loop is counting each second elapsed.
There is a separate class called Function:
public class Function {
public static int Move (int result){
result = 1 + counter;
return result;
}
}
So as you can see, inside the Function class's Move method, I want to be able to use the counter variable's new value, which increases with each passing second, to calculate the value of a different variable which will then be returned to the main method.
The problem is that I can't figure out how to pass the value of counter to the Move method inside the Function class to begin with.

I'm not shure if i understand what you want to do correctly, depending on where exactly you will need that result variable later i think your coude should look something like this:
public class Main {
int counter;
public static void main(String[] args) throws InterruptedException {
int one = 1;
counter = 0;
while (one<100){
Thread.sleep(1000);
counter += 1;
one++;
}
}
public int getCounter() {
return counter;
}
}
public class Function {
public static int move (int result, Main main){
result = 1 + main.getCounter();
return result;
}
}
You can use Function.move() anywhere you need it's value in your Programm now.
Beware, though, that you will need your code using the Function.move() to run in a different Thread as the Main Thread. Otherwise it will always return 101 or 1, as the while loop will always be running before or after your call to Function.move(), depending on where you call it (except if you call it from within the while loop, but then you counld just use counter++ without the need to have an extra class)

Related

Use counter to keep track from a function to global level

public static void main(String args[]){
extract("e:\\");
}
public static void extract(String p){
File f=new File(p);
File l[]=f.listFiles();
int counter = 0;
for(File x:l){
if(x.isDirectory()) extract(x.getPath());
else if(x.getName().endsWith(".mp3"))){
counter = counter + 1;
}
}
// I want to count and return value at last
}
Using this method(above), resets the counter every time when for loop ends.
So here, I want to count even when the for loop ends so that I can keep track of the number of .mp3 files.
I want to count and return value at last.
Return the current counter and make sure you add the response when you call recursively back to the counter.
public static void main(String args[]) {
int count = extract("../");
}
public static int extract(String p) {
File f = new File(p);
File l[] = f.listFiles();
int counter = 0;
for (File x : l) {
if (x.isDirectory()) {
counter += extract(x.getPath());
} else if (x.getName().endsWith(".mp3")) {
counter++;
}
}
return counter;
}
You should not use recursion like that. (Recursion should always have a termination condition to avoid running in a loop forever!
I think the problem is, that you create new Integers every time you call your method, so you will eventually override your old value or even use many different Integers to count.
You can wrap everything in a class in which you keep track of one integer.
Some pseudo-code:
public class Mp3Counter {
private int numberOfMp3 = 0;
public void extract(...) {
if (foundMp3) {
this.numberOfMp3 += 1;
}
}
}

Can't get my integer to increase constantly in method

I am fairly new to java (and most programming languages as a whole) and am trying to get some unfamiliar concepts down, one of which is recursion. To test it out I tried making it so that a number would constantly increase and get displayed.
public static void recursionTest() {
int numb = 0;
System.out.println(numb);
numb += 1;
recursionTest();
}
I tried writing it out like this, but it will only print the number 0 constantly with no increase. I then tried putting before println, but it only produced the number 1. I then tried replacing with a while loop.
public static void recursionTest() {
int numb = 0;
System.out.println(numb);
while (numb != -1) {
numb =+ 1;
}
recursionTest();
}
This ended up printing out just a single 0, I then tried moving it above println like I did before, but it then didn't display anything. Is there something I'm missing? Sorry if my question is stupid.
As you have defined it, numb is a local variable scoped within the method. It's created with the instruction int numb = 0 at the beginning of each call of the method, and destroyed at the end of it. Each time you call the method (even if the call is recursive) is a different variable. With the same name in the code, but it's a different one.
In order to achieve a counter you should either define numb as a static field of the class or pass as parameter to the method. You can do something like the following:
Option 1 (static field):
public class TheClass {
static int numb = 0;
public static void recursionTest() {
System.out.println(numb);
numb += 1;
recursionTest();
}
}
Option 2 (pass as parameter):
public class TheClass {
public static void recursionTest(int numb) {
System.out.println(numb);
numb += 1;
recursionTest(numb);
}
}
In the second attempt you are doing the System.out.println outside the while loop, so you are printing the value only once. Moreover, the recursive call is never being done due to the infinite while loop, but in the case you put a limit to the loop, the new call to the same method will result in the counter being reset because the same reason as before.
You should read up about the scope and lifespan of variables in Java. You declare a local variable inside the function, which is "created" and initiated (to 0) when you write:
int numb = 0;
This variable is only visible inside this current function call. After your function is executed the variable and its value is invalidated and destroyed. When calling the function again, the variable is created and initiated (to 0) again.
If your variable needs to "survive" multiple calls of your function consider to declare it outside of the function:
private static int numb = 0;
public static void recursionTest() {
System.out.println(numb);
while (numb != -1) {
numb =+ 1;
}
recursionTest();
}
Or pass it as a parameter:
public static void main(String[] args) {
recursionTest(0);
}
public static void recursionTest(int numb) {
System.out.println(numb);
while (numb != -1) {
numb =+ 1;
}
recursionTest(numb);
}

Printing integers in the ascending order recursively

Today, I have taken an exam, and there was a question:
Write a method which prints integer numbers in the ascending order recursively from 1 to n:
public class PrintIntegersAscendingOrder {
static int counter = 0;
public static void PrintIntegersAscendingOrder (int n)
{
if (n == 1)
{
System.out.printf("%d\n", ++counter);
}
else
{
System.out.printf("%d ", ++counter);
PrintIntegersAscendingOrder(n-1);
}
}
public static void main (String args[])
{
PrintIntegersAscendingOrder(5);
}
}
Although this method worked now, the initial question didn't ask for the class definition, but the method. There, I couldn't be able to fit counter (I have written counter inside the if on the paper, but it gives an error in the program). How can I write the method precisely and correctly without counter variable?
You can do it like this:
public class IntegerAscendingOrder {
public static void main(String[] args) throws Exception {
printIntegersAscendingOrder(n);
}
private static void printIntegersAscendingOrder(int i) {
if (i < 1) {
return;
}
printIntegersAscendingOrder(i-1);
System.out.println(i);
}
}
You don't need the counter variable in the class, using recursion you can limit the method call within the method itself.
Notice the if (i < 1) {return;} line, this will terminate the recursive method call(s).
This article should help you Getting started with recursion
Do it as follows:
public class Main {
public static void printIntegersAscendingOrder(int n) {
if (n == 0) {
return;
}
printIntegersAscendingOrder(n - 1);
System.out.printf("%d ", n);
}
public static void main(String args[]) {
printIntegersAscendingOrder(5);
}
}
Output:
1 2 3 4 5
As #RobOhRob has already pointed out, the counter defeats the purpose of recursion in your code. When you are calling a function recursively, you need to analyse three important things:
When to stop the recursive call
Processing before making the recursive call
Processing before making the recursive call
Since you are already decreasing the parameter by 1 and passing it to the method to call it recursively, you can simply make use of this parameter instead of creating an additional variable (e.g. counter).
In your code you have defined in your class a method PrintIntegersAscendingOrder having the same name of the class PrintIntegersAscendingOrder containing it. This is an error that can be avoided for example renaming the including class to PrintIntegers. Below the code of class without the error and with the recursive method:
public class PrintIntegers {
public static void PrintIntegersAscendingOrder(int n) {
if (n > 0) {
PrintIntegersAscendingOrder(n - 1);
System.out.printf("%d\n", n);
}
}
public static void main (String args[]) {
PrintIntegersAscendingOrder(5);
}
}

recursion program to add and subtract a number

I want to implement this program but it throws errors on every function call and runs an infinite loop.
class abc
{
public static void main(String[] args) {
int n=16;
calll(n);
}
static int calll(int n)
{
if(n>0)
{
n=n-5;
calll(n);
return n;
}
else
{
n=n+5;
calll(n);
return n;
}
}
}
There is no end condition to your function.
Whether n is greater than 5 or not you run the calll function, which then runs the calll function again to infinite.
You need a conditon that will end the recursion, for instance changing the call function to this:
static int calll(int n)
{
if(n>0)
{
n=n-5;
calll(n);
return n;
}
else
{
return n;
}
}
However the function is still rather pointless as you don't actually do anything with n. Keep in mind that the n that you define in the main function is never modified.

multi-threading: thread gets own copy of method, but parameter is shared

I want to confirm my understanding on this -
public class Main {
private static int j = 0;
private int k = 0;
public static void main(String[] args) {
Main obj = new Main();
obj.doProcess();
}
public void doProcess() {
ExecutorService service = Executors.newFixedThreadPool(10);
for (int i = 0; i < 4; i++) {
service.submit(new SingleProcessor());
}
}
public static void myStaticMethod() {
System.out.println("my static method");
int i = 0;
i++;
j++;
System.out.println("i " + i);
System.out.println("j " + j);
}
public void myInstanceMethod() {
System.out.println("my instance method");
int i = 0;
i++;
k++;
System.out.println("k " + k);
}
private class SingleProcessor implements Runnable {
#Override
public void run() {
System.out.println("single run starts" + Thread.currentThread().getName());
myStaticMethod();
myInstanceMethod();
}
}
}
When a thread runs, it gets it's own copy of methods, be it static or instance method - any variable created inside these methods are local and specific to that thread. It's like multiple 'instances' of this method are getting executed simultaneously, any variable created inside is not shared (it's local).
However parameters (static or instance) are shared by threads.
So in above example -
i is local and specific to thread.
j is shared.
k is shared.
output -
single run startspool-1-thread-1
single run startspool-1-thread-2
my static method
single run startspool-1-thread-3
my static method
i 1
i 1
j 2
j 2
my instance method
my instance method
k 1
k 2
my static method
i 1
j 3
my instance method
k 3
single run startspool-1-thread-4
my static method
i 1
j 4
my instance method
k 4
Is my understanding 100% correct? Anyone would like to put it in better words?
Thanks.
If I followed correctly-- that should be correct.
Its the basic understanding of stack vs heap. Anything declared on the stack (variables declared in a function) is only available locally. Variables declared on the heap can be access globally or by any function within its scope.
So if you have a thread processing a function all the variables inside the function can only be accessed within that function. BUT if you have a global variable and two threads both threads can access that variable. The catch is that you have to make sure they don't override one another if they write to that variable.
The solution for this is locking a heap variable while one thread is read/writing to it and then unlocking it when its done.
What do you think would happen if you run the code below? You'll see a similar output, but in different order, probably. i is a static variable and is in static scope, j is in method scope, k is an instance variable of Main. Same stuff with threads. Scopes work the same with threads. You should read about inner classes instead.
public class Main {
private static int j = 0;
private int k = 0;
public static void main(String[] args) {
Main obj = new Main();
obj.doProcess();
}
public void doProcess() {
for (int i = 0; i < 4; i++) {
SingleProcessor sp = new SingleProcessor();
sp.run();
}
}
public static void myStaticMethod() {
System.out.println("my static method");
int i = 0;
i++;
j++;
System.out.println("i " + i);
System.out.println("j " + j);
}
public void myInstanceMethod() {
System.out.println("my instance method");
int i = 0;
i++;
k++;
System.out.println("k " + k);
}
private class SingleProcessor implements Runnable {
#Override
public void run() {
System.out.println("single run starts" + Thread.currentThread().getName());
myStaticMethod();
myInstanceMethod();
}
}
}
You're right.
A static variable could be intrepreted as a Singleton in your application, no matter how many Threads you have, they'll always have a reference to the same variable.
As for your instance variable 'k', it only works because your nested class is not static, which means you need an instance of Main to be able to instanciate SingleProcessor. Your instance of SingleProcessor will, under the hood' have a hidden variable referencing you Main instance. It's the same as if you'ld write this:
public class SingleProcessor implements Runnable {
private Main main;
public SingleProcessor(Main main){
this.main = main;
}
#Override
public void run() {
System.out.println("single run starts" + Thread.currentThread().getName());
Main.myStaticMethod();
this.main.myInstanceMethod();
}
}
And give all of your SingleProcessor the same Main instance.
All of this is dangerous, a Thread may acquire a variable the same time another Thread is modifying it. There's alot of advanced topics about Thread safety. For simple types, you can use Atomic variables, se Concurrency package JavaDoc.

Categories