Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread getName() returns wrong name

Ok, I know it's probabblly mz bad understanding of how threads really work, but until someone helps me understand I'll believe that it's a bug :)

In my Main class and its main() method I have:

public static void main(String args[]){
    StoneBucket stoneBucket = new StoneBucket();    
    StonePutter spRunnable   = new StonePutter(stoneBucket);
    StoneThrower stRunnable  = new StoneThrower(stoneBucket);
    StoneThrower stRunnable2 = new StoneThrower(stoneBucket);

    //Create the Threads that will take the Runnables as arguments
    Thread puttingThread = new Thread(spRunnable);
    Thread throwingThread = new Thread(stRunnable);
    Thread throwingThread2 = new Thread(stRunnable);

    puttingThread.setName("Putter");
    throwingThread.setName("Thrower 1");
    throwingThread2.setName("Thrower 2");
    [...]

And then in my StoneThrower class I have

public class StoneThrower implements Runnable{

private StoneBucket sb;
private String name;

public StoneThrower(StoneBucket _sb){
    this.sb = _sb;
}   

public void run(){

    name = Thread.currentThread().getName();        
    System.out.println("T::"+name+" started...");       
    int count = 0;      
    while(true){
            [...]

When I compile and run this code I'm getting:

Screenshot of 2 threads...

So, my question is why do both of these threads return the same name for currentThread().getName() ? When they were created they were assigned the name through threadX.setName("XXX") and those runnables are started by calling threadX.start()... Could someone please clarify me this?

EDIT: I accepted the correct answer because changing the stRunnable to stRunnable2 the behaviour is as expected. The real question is now why does this happen. I create two threads and start them separately. How is it posibble that the run() method (called once when the thread's created) returns wrong name ?

like image 610
luigi7up Avatar asked Nov 28 '12 20:11

luigi7up


2 Answers

This happens because you store thread name in instance variable name of your StoneThrower. Because of concurrency, second thread overrides value of name that first thread has just set and both of them output the same value.

Here is your scenario:

1. Thread1#start
2. Thread2#start
3. Thread1#runnable#run -> runnable.name = 'Thrower 1'
4. Thread2#runnable#run -> runnable.name = 'Thrower 2' // overrides
5. Thread1#runnable#run -> System.out.println(runnable.name)
6. Thread2#runnable#run -> System.out.println(runnable.name)
like image 102
hoaz Avatar answered Sep 28 '22 07:09

hoaz


You create both threads with the same runnable:

Thread throwingThread = new Thread(stRunnable);
Thread throwingThread2 = new Thread(stRunnable);
                                    ^^^^^^^^^^ stRunnable2?

You store the thread name in an instance variable of the Runnable object. Since the object is shared by the two threads, the second thread to execute name = Thread.currentThread().getName() overwrites the first thread's name with its own.

like image 43
NPE Avatar answered Sep 28 '22 07:09

NPE