0

The relevant summary of my code is this:

public class A {
    String aString;

    public static void main(String[] args) {
        B b = new B();
        new Thread(b).start();
    }
    public static class B implements Runnable {
        public void run() {
            aString = "foo";
        }
    }
}

I have had a few months of Java coding experience but thread and dynamic vs. static is still rather new to me. In order for the thread to execute properly, class B must be static, or else only the thread executes, not both. My goal is to obviously have the thread execute in the background so that other code that I may have in class A can execute simultaneously. Problem is, if class B is static, I can't manipulate the string aString, as I get the exception non-static variable aString cannot be referenced from a static context.

I've looked up information on this but I have not found anything that relates to fixing this issue in threads. My question is, how can I manipulate aString within class B and still get the thread to work properly (both classes running, not just class B)?

1
  • 1
    static has nothing to do with threads. You would have the same problem without threads. For example, with new B().run(). Or if you just wrote aString = "foo" in main. Commented Feb 13, 2015 at 5:28

3 Answers 3

2

To make your example work, you'll need something like this:

public class A {
    volatile String aString;

    public static void main(String[] args) throws InterruptedException {
        A a = new A();
        Thread t = new Thread(a.new B());
        t.start();
        t.join(); // wait for t to finish
        System.out.println(a.aString); // prints "foo"
    }

    class B implements Runnable {
        public void run() {
            aString = "foo";
        }
    }
}

Resolving the static issue is the easy part - see code for how.

I hope the rest of the code helps illustrate some of the issues you need to cater for when using threads.

Sign up to request clarification or add additional context in comments.

4 Comments

Thing is though, I don't want to wait until the thread finishes. This was just an example code - in the actual program I have while loops going on in both classes, hence why I'm using the threads. I removed t.join() but still both threads don't execute at the same time.
@Xyspade for the example given, you need join() otherwise there's a good chance the main method will execute the println() before the thread even executes - remembering that calling start() on a thread just schedules it to start, there's no guarantee when it will execute. Your problem may be that you need to make your fields volatile, which ensures their values are not cached in other threads - and your main threads "sees" them change.
Actually, I've been looking into this, and it's possible that the problem may be elsewhere. I will keep everyone updated. Thanks once again.
Yes, this solution worked for me; the problem I was experiencing was elsewhere in the code. Thank you everyone!
0

B is static, so only only exists at the class level, and can therefore not see instance variables of its parent class

public class A {
    String aString;  // <== instance variable

    public static void main(String[] args) {
        B b = new B();
        new Thread(b).start();
    }
    public static class B implements Runnable {  // <== static class
        public void run() {
            aString = "foo";
        }
    }
}

Possible fix. Make aString static too

public class A {
    static String aString;

Possible fix. Make B non-static. This is where it gets a bit weird. B now only exists at the instance level of A, so you need to create an A instance first.

public class A {
    String aString;

    public static void main(String[] args) {
        B b = new A().new B();  // <== need to create an A before a B
        new Thread(b).start();
    }
    public class B implements Runnable {
        public void run() {
            aString = "foo";
        }
    }
}

3 Comments

B b = new A().new B(); // <== create via A - I've never seen this notation before - nice!
I only discovered it in the OCJP book, it's crazy isn't it!!?, a bit like Ruby's Object.new
@KevinDay that's because you very rarely need to create an instance of an inner class from outside the outer class
0

You are asking an object instance of class B (which you create using new B() )to access a member variable of an object instance that you haven't created. In your code, there is no object of class B created.

I think that you may be thinking that running the main() method in class A is somehow instantiating an instance of class A - this is not the case.

The following will work because you are creating an instance of A and making that available to your instance of B.

public class A {
    String aString;

    public static void main(String[] args) {
        A a = new A();
        B b = new B(a);
        new Thread(b).start();
    }
    public static class B implements Runnable {
        private final A a;

        public B(A a){
          this.a = a;
        }

        public void run() {
            a.aString = "foo";
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.