Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java thread start not working

I have a simple exercise I am trying to do involving threads.

(a) Create a class called SumAction that implements Runnable. The class contains 3 instance variables – start, end, and sum. start and end are initialized by the constructor. sum is set to 0.

(b) The run() method should have a for loop which should find the sum of all values from start to end. There should be a method getSum() to return the value of sum.

(c) In main create 2 instances of this Runnable class, one which takes 1 and 10 as parameters, the other takes 10 and 20.

(d) Pass these instances to 2 thread constructors to make threads t1 and t2.

(e) When the threads have finished, call getSum to get the sum value from both threads to find the overall total.

I am pretty sure I am doing this right but I am still getting the sum value of 0 back.

Here is my class

public class SumAction implements Runnable {

private int start, end, sum;

public SumAction(int start, int end) {
    this.start = start;
    this.end = end;
    sum = 0;
}

@Override
public void run()
{

    for (int i = start+1; i < end; i++)
    {
      sum += i;  
    }

}

public int getSum() {
    return sum;
}
}

Here is the main

    SumAction run1 = new SumAction(1, 10);

    SumAction run2 = new SumAction(10, 20);

    Thread t1= new Thread(run1);

    Thread t2= new Thread(run2);


    t1.start();

    t2.start();


    System.out.println("Sum 1 : " + run1.getSum());

    System.out.println("Sum 2 : " + run2.getSum());
like image 568
Michael Grinnell Avatar asked Feb 04 '23 12:02

Michael Grinnell


1 Answers

You're not waiting for the threads to finish. Your main thread can call getSum before the other threads are done calculating or before they have even started. Also it's possible the updated values may not be visible to the main thread even if the thread does happen to finish before the println.

Call join on the threads to wait til they have finished, add this after starting the threads and before the printlns:

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

This makes sure the main thread waits until the other threads finish before trying to print the sums, and also takes care of the visibility issue.

In many cases having a thread read from a field written to by another thread is problematic (buggy, implementation-dependent, or just confusing and hard to reason about) if adequate precautions (synchronization, making the field volatile, etc.) are not taken. But in this code if you call join then no additional synchronization is required for the main thread to be assured to see the latest value of getSum, because there is an applicable happens-before rule. Quoting from the Oracle tutorial:

When a thread terminates and causes a Thread.join in another thread to return, then all the statements executed by the terminated thread have a happens-before relationship with all the statements following the successful join. The effects of the code in the thread are now visible to the thread that performed the join.

The join method throws InterruptedException, which is a checked exception thrown if the thread enters a sleep or wait state after having its interrupt flag set. For a simple example program where you're not actually interrupting anything you can add it to the throws clause of the main method.

like image 83
Nathan Hughes Avatar answered Feb 07 '23 18:02

Nathan Hughes