Reputation: 23790
Here is the code I have:
/* User: [email protected] Date: 21/02/15 Time: 19:53 */
public class DriverClass {
public static void main(String[] args) throws InterruptedException {
int upper = 15;
Integer sumValue = null;
Thread thread = new Thread(new Summation(upper, sumValue));
thread.start();
thread.join();
System.out.println(sumValue);
}
}
and the Summation class:
class Summation implements Runnable {
private int upper;
private Integer sumValue;
public Summation(int upper, Integer sumValue) {
this.upper = upper;
this.sumValue = sumValue;
}
public void run() {
System.out.println("Thread started...");
int sum = 0;
for (int i = 0; i <= upper; i++) {
sum += i;
}
System.out.println("Sum is:" + sum);
sumValue = sum;
}
}
I will see in the console:
Thread started...
Sum is:120
null
Why the last line is 'null' ? I am expecting to see 120 again?
Upvotes: 2
Views: 73
Reputation: 691715
OK. Let me explain with a picture. First you create a reference in the main method and assign null to it:
main
----
sumValue -----> null
Then you pass this reference to the Summation constructor. This creates a copy of the reference:
main
----
sumValue -----> null
^
Summation |
---- |
sumValue --------
Then the Summation.run() emthod assigns a new integer value to the Summation.sumValue reference:
main
----
sumValue -----> null
Summation
----
sumValue -----> 120
As you see, the reference in the main method still points to null
. That's why null is printed.
What you can do, instead, is pass a reference to a mutable object, whose state can change (like an AtomicInteger for example):
main
----
sumValue -----> AtomicInteger(0)
Then pass it to Summation:
main
----
sumValue -----> AtomicInteger(0)
^
Summation |
---- |
sumValue --------
Then in Summation, modify the state of the AtomicInteger: sumValue.set(120)
:
main
----
sumValue -----> AtomicInteger(120)
^
Summation |
---- |
sumValue --------
And then, when printing the AtomicInteger in the main method, you'll have 120, because then the main method and the Summation object have two references pointing to the same object.
Or better, you could store the result as an Integer in the Summation object, and ask for the result in the main method once the computation is done:
System.out.println(summation.getSumValue());
Upvotes: 4
Reputation: 18242
This happens because Integer is immutable.
You are passing your sumValue to Summation via the constructor, but in the constructor a new Integer is created to copy the value of the one you are passing to it.
To better understand what is happening here you may want to take a look at this article keeping in mind that you are working with an immutable object (your Integer object)
Edit:
Creating your own class extending Integer? take a look at this immutable class should be final?
You can instead create an accessor a getter for your sumValue:
public class DriverClass {
public static void main(String[] args) throws InterruptedException {
int upper = 15;
Integer sumValue = null;
Summation sum = new Summation(upper, sumValue);
Thread thread = new Thread(sum);
thread.start();
thread.join();
sumValue = sum.getSumValue();
System.out.println(sumValue);
}
}
class Summation implements Runnable {
private final int upper;
private Integer sumValue;
public Summation(int upper, Integer sumValue) {
this.upper = upper;
this.sumValue = sumValue;
}
@Override
public void run() {
System.out.println("Thread started...");
int sum = 0;
for (int i = 0; i <= upper; i++) {
sum += i;
}
System.out.println("Sum is:" + sum);
sumValue = sum;
}
public Integer getSumValue() {
return sumValue;
}
}
Upvotes: 2
Reputation: 88796
This code
sumValue = sum;
overwrites Summation
's sumValue
with a new reference rather than updating the value of the reference that's already there.
If you want to return values from a thread, you need to use a Callable
instead of a Runnable
.
However, Callable
s can't be used using Thread directly. Instead you have to use an ExecutorService
.
The easiest way to do this would be:
ExecutorService service = Executors.newSingleThreadExecutor();
Future<Integer> future = service.submit(new Summation());
Integer sumValue = future.get(); // The Future equivalent of join
Note that this uses a Future<Integer>
, which is a value that will be returned in the future. We use get
which blocks unless the Future
finishes processing.
Note that you'll have to redesigned Summation to implement Callable<Integer>
instead of Runnable
, and change public void run()
to public Integer call()
and return sum;
(or sumValue
).
Upvotes: 1
Reputation: 290
Inside the thread you are assigning SumValue to a new Object, so outside of the thread it is still null. If you plan on running this thread multiple times to get multiple sums, try storing the sums in a Map where the key is the upper number and the value is the sum.
So:
Map<Integer,Integer> sumMap = new TreeMap<Integer,Integer>();
Thread thread = new Thread(new Summation(upper, sumMap));
public Summation(int upper, Map<Integer,Integer> sumMap) {
this.upper = upper;
this.sumMap= sumMap;
}
public void run() {
System.out.println("Thread started...");
int sum = 0;
for (int i = 0; i <= upper; i++) {
sum += i;
}
System.out.println("Sum is:" + sum);
sumMap.put(upper,sum);
}
Upvotes: 1
Reputation: 596
In the constructor of Summation
you set the field sumValue
.
Then in the function run
you set the field sumValue
again:
sumValue = sum;
But you're setting the field to a new Integer
instance. You are not setting the old Integer instance to a new value.
That is why the sumValue
in the main thread isn't changing, it's never been set to anything but null
.
Upvotes: 1