简体   繁体   中英

Java Thread issue with variable placement

I'm trying to run a simple sum from one to upper bound function over 10 threads concurrent Java threads. My main current issue is the placement of the variables for upperBound, lowerBound, sum, and i. I would like to capture the i variable update the sum calculation, but i get the error "local variable needs to be declared final." I'm a beginner to Java, but from what I've read about declaring a variable final, is that it keeps the variable unmodifyable--not my goal..right?

public class threads {
    public static void main(String[] args) {
    System.out.println(Thread.currentThread().getName());
    for(int i = 0; i < 10; i++) {
        new Thread("" + i) {
            public void run() {
                int sum = 0;
                int upperBound = 22;
                int lowerBound = 1;
                long threadID = Thread.currentThread().getId();
                for (int number = lowerBound; number <= upperBound; number++){
                    sum = sum + number + i;
                }
                System.out.println("Thread: " + threadID + " is running now and will compute the sum from 1 to " + (upperBound + i));
                System.out.println("Thread id " + threadID + " computes sum " + sum);
             }
           }.start();
        }
    }
}

Yes, declaring the i variable final so you can use it from within the anonymous Thread subclass will prevent you from modifying it. But you can just make another variable with the current value of i and make that final:

for (int i = 0; i < 10; i++) {
    final int iCopy = i;
    /* use iCopy in the Thread subclass */
}

Of course, if you need a mutable iCopy in the inner class body (in this case you don't, but in general you might), you'll have to make a (non-final) copy of iCopy in the class.

This might seem annoying, but Java's trying to help you out here: if you could use i from within the other thread, what value should it see for i -- the value when the inner class is instantiated (an implicit copy), or the value at the time the thread actually runs (which would be 10 after the loop finishes)? Many languages with closures choose the latter interpretation. The Java designers decided to prevent confusion by only letting you use final variables in inner classes (and lambdas), which will only have one value.

A variable that you access in the public void run(){...} method should either be declared as final as a security measure created by java. A final variable cannot be reassigned a value after it has been assigned with one. You can also use a GLOBAL variable in the run method(recommended) as it can be reassigned a value again in the run method. In your case, the variable i has to be declared globally or declared as a final variable, or any other final variable should be made equal to i in each loop. Your working code will be :-

for(int i = 0; i < 10; i++) {
    final int FINAL_I = i;
    new Thread("" + FINAL_I) {
        public void run() {
            int sum = 0;
            int upperBound = 22;
            int lowerBound = 1;
            long threadID = Thread.currentThread().getId();
            for (int number = lowerBound; number <= upperBound; number++){
                sum = sum + number + FINAL_I;
            }
            System.out.println("Thread: " + threadID + " is running now and will compute the sum from 1 to " + (upperBound + FINAL_I));
            System.out.println("Thread id " + threadID + " computes sum " + sum);
         }
       }.start();
    }
}

You can also use :-

for(int i = 0; i < 10; i++) {
    new Thread("" + i) {
        int i = this.i;
        public void run() {
            int sum = 0;
            int upperBound = 22;
            int lowerBound = 1;
            long threadID = Thread.currentThread().getId();
            for (int number = lowerBound; number <= upperBound; number++){
                sum = sum + number + i;
            }
            System.out.println("Thread: " + threadID + " is running now and will compute the sum from 1 to " + (upperBound + i));
            System.out.println("Thread id " + threadID + " computes sum " + sum);
         }
       }.start();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM