views:

93

answers:

4

The following thread is made to run unpredictably. Sometimes it may print ABC and others 123. I don't get why it's able to print ABC. Please explain its flow of execution.

public class ArrayDeclaration implements Runnable {

    String [] s;
    public ArrayDeclaration (String []s){
        this.s=s;
    }

    public void run() {
        synchronized (this){
            try
             {
                wait(5000);
                System.out.print(s[0]+s[1]+s[2]);
            }
            catch(InterruptedException ie){
        }
    }
         }

    }
    /**
     * @param args the command line arguments
     */class Test{
    public static void main(String[]args)throws Exception {


        String[] s = new String []{"1","2","3"};
      ArrayDeclaration myRunnable = new ArrayDeclaration(s);
        // TODO code application logic here

        Thread t1 = new Thread(myRunnable);
        t1.start();
        t1.join(5000);
          s[0]="A";
          s[1]="B";
          s[2]="C";
    }

}

I don't get the scope of the String array. Why is it (sometimes) changed to ABC and printed? Shouldn't the changes just affect its scope within main? Does this behavior has something to do with the String pool?

A: 

For one thing, you wait 5 secs in the thread, and you also join with a max wait time of 5 seconds.

Timing is difficult, the API does not guarantee exact timing. So I think that sometimes the join actually waits 4998 millis and the wait() is 5002 millis at which time the array is already changed. Not always of course, sometimes the other way around and then it prints 123. (Times mentioned are an example).

You can have a sequantial flow by using join() without a timeout.

extraneon
+2  A: 

It's able to do that because of the timeout on the call to join combined with the wait of the same length in the ArrayDeclaration. So, you start the thread, which immediately does a wait(5000). You join for up to 5000 millis. The wait and the join both finish close enough to the same moment that one thread or the other might get the next time slice for execution depending on many external factors. In some cases, the main thread gets the first chance, so it sets the array members before the other thread prints them. In other cases, the printing thread gets the first chance.

If the join and wait were not the same length, it would be more predictable.

Clay Fowler
A: 

The timeout on your join expires before the timeout on the wait. Even though they are both set to the same wait interval, whichever thread happens to run first and have its timeout expire will be fairly random. Thus resulting in the array contents being changed before the print occurs in random cases where the join expires first.

Robin
+1  A: 

Both timers, wait and join have 5000 milliseconds as arguments, because computer clocks typically have a resolution of about 30ms, both timers run out at approximately the same time, making it impossible to predict what happens first, the code after the wait or the code after the join.

Changing the argument to join to 6000 milliseconds would make sure the thread can run its course and resulting in a successful join and printing 123 always.

rsp
It most likely would, but I hardly think that this is the way to go about doing it.
San Jacinto
@San; The code as it is results in unpredictable behaviour, if that needs to be resolved you need to increase the timeout on the `join` call. What other solution did you have in mind?
rsp
You (i.e. the programmer, not necessarily rsp) need to restructure the communication between threads so that you're not using timers to accomplish it. That being said, this is moot now that we find out it was an example from the textbook, probably addressing this very topic.
San Jacinto