0

how can I assign a value to String outside of run() in java. It's starting new thread, running and obtaining value, then is supposed to return it. if I try to just set string = value in thread, it tells me I need to change String to final which wont work then

Any suggestions on this?

arleitiss
  • 107
  • 2
  • 13
  • 1
    Though I'm not completely sure this is what you need, if you want to return a value from a separate thread, check out the Callable interface http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Callable.html and use an Executor –  Apr 23 '13 at 01:00

2 Answers2

1

"it tells me I need to change String to final which wont work then"

It seems to hint me that your problem is not about threading, but something related (anonymous) inner class access to variables in enclosing scope.

I bet what you are doing is something like this:

class Foo {
    public void foo() {
        String myString = "abc";

        Thread t = new Thread(
            new Runnable() {
                @Override
                public void run() {
                    myString = "xyz";
                }
            }
        };
        t.start();
        t.join();
        System.out.println("result :" + myString);
    }
}

You will find compiler is complaining for "myString should be final" something like that. It has nothing to do with multi-threading. It is simply that for anonymous inner class, it have access to only final variables in the enclosing scope.

Given String being immutable, one of the way to solve by keeping your original code structure is, to have some holder of String which is final. String array is a possible choice, or you can make a holder as simple as this:

public class StringHolder {
    String value;
    public StringHolder(String value) {
        this.value = value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public value getValue() {
        return this.value;
    }
}

and change your code to something like this:

class Foo {
    public void foo() {
        String myString = "abc";
        final StringHolder myStringHolder = new StringHolder(myString);

        Thread t = new Thread(
            new Runnable() {
                @Override
                public void run() {
                    myStringHolder.setValue("xyz");
                }
            }
        };
        t.start();
        t.join();
        System.out.println("result: " + myStringHolder.getValue());
    }
}

However, this is not the recommended way for getting result from thread.

I strongly suggest you change your code structure, and look into usage of Future (and related classes).

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
0

As Ron Dahlgren commented, the correct way to do this is with a Callable. The hack to do this is to assign your string to the first element of a final String[] oneStringReference = new String[1];

public class MyCallable implements Callable {
    private Object param1;
    private Object param2;
    private Object param3;

    public MyCallable(Object param1, Object param2, Object param3) {
        this.param1 = param1;
        this.param2 = param2;
        this.param3 = param3;
    }

    public Object Callable() {
        ...
    }
}
Zim-Zam O'Pootertoot
  • 17,888
  • 4
  • 41
  • 69