Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

accessing shared variable from inside a Runnable class

I need to define a shared variable in my Main class's main() method. I need two threads to be able to access that shared variable. Im creating the threads by implementing the Runnable interface and implementing the abstract run() method of the interface. How do i refer to the shared variable defined in the Main class's main() method from within the run() method defined in my class that implements the Runnable interface? Obviously just calling them by name is not working - as they appear out of my Runnable class's scope.

EDIT - apologies, here is a simple example

public Class DoThread implements Runnable {

    public void run(){
        sharedVar += 1
    }


}

and in a separate .class file:

public Class Main {

    public static void main(String[] args) {
        int sharedVar = 0;

        Thread t1 = new Thread(new DoThread());
        Thread t2 = new Thread(new DoThread());

        t1.start();
        t2.start();

        t1.join();
        t2.join();

    }


}

so should i be creating an object to store the shared var in and then passing that object to both the DoThread() constructors when creating the threads? I get confused sometimes between when java passes by ref or passes by var, so if i do it this way, will changes to the shared var by t1 be seen by t2?

like image 371
Dave Anderson Avatar asked Aug 22 '11 12:08

Dave Anderson


3 Answers

Well, if you declare a local variable you won't be able to refer to that anywhere other than in classes created within that method.

Where are you implementing Runnable? If it's in the same class, then you could either make it an instance variable and make main set the variable on the same instance that you're creating the thread from, or make it a static variable. If Runnable is implemented in a different class, then when you construct an instance of that class you could give it the data it needs - it's not clear exactly what that means at this point... As others have said, code would be useful. (For example, do the threads need to be able to see changes in the original data?)

As an aside, threading is relatively advanced, whereas propagating data between classes is relatively basic. If you're new to Java, I'd recommend getting started on easier things than threading.

EDIT: For your example, you should use an AtomicInteger, like this:

import java.util.concurrent.atomic.AtomicInteger;

class DoThread implements Runnable {

    private final AtomicInteger counter;

    DoThread(AtomicInteger counter) {
        this.counter = counter;
    }

    public void run() {
        counter.incrementAndGet();
    }
}

public class Test {
    public static void main(String[] args) throws InterruptedException {
        AtomicInteger shared = new AtomicInteger(0);

        Thread t1 = new Thread(new DoThread(shared));
        Thread t2 = new Thread(new DoThread(shared));

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println(shared.get()); // Prints 2
    }
}
like image 85
Jon Skeet Avatar answered Nov 11 '22 06:11

Jon Skeet


Code would be useful.

If you are using an anonymous class, then you can declare the variables as final and they will be accessible in the anonymous class.

public void main(String[] args) {
    final int myvar = 0;
    new Thread(new Runnable() {
        public void run() {
            System.out.println("myvar: "+myvar);
        }
    }).start();
}
like image 22
Charles Goodwin Avatar answered Nov 11 '22 06:11

Charles Goodwin


You need to pass a reference to the shared value. If its isn't a reference already you need to change it to an AtomicReference, AtomicInt etc or an array of the value you want to share.

like image 21
Peter Lawrey Avatar answered Nov 11 '22 07:11

Peter Lawrey