1

I have a java threading code. I have 3 threads, I have given names to all of them. 2 consumer threads name Consumer1 and Consumer2. A producer thread named Producer. I have a synchronized method where I try to compare the names of thread. I want that if thread name is consumer2, I want it to sleep for some time. Like so:

public synchronized String getReferer()
    {
        try{
            String threadName = Thread.currentThread().getName();
            System.out.println("Thread name: "+threadName);
            System.out.println(" compatre"+threadName=="Consumer2");
            if(threadName == "Consumer2"){
                System.out.println("It is consumer2. ...wait, you #$%^!!!");
                //this.wait();
            }
        }catch(Exception e){
            this.displayAndExit(e);
        }
        String line = "";
        int i = 0;
        try{
            finished = 0;
            if(this.hostnames2.isEmpty()){
                line = null;
            }else{
                line = this.hostnames2.take();
            }
        }catch(Exception e){
            this.displayAndExit(e);
        }
        return line;
    }
}

I start all thread one after another, first producer and the consumers. What happens is if I s.o.p threadName I can see Consumer1 and Consumer2 all over the place. But in second s.o.p I see something like this !!!

Thread name: Consumer2 false

Now since method is synchronized, a thread will hold lock onto it when it enters. So if it is Consumer2 then how come it's comparison with string "Consumer2" fail when both statements are just back to back??

This is the main method and invocation of threads.

public class OffensiveFilterApplicator 
{
    public static void main(String [] args)
    {
        String pathToCSV = "src/unique_referer_dump3.txt";
        CSVResourceHandler csvResHandler = new CSVResourceHandler(pathToCSV);
        HostnameFileData hfd = new HostnameFileData();
        HostnameReader hr = new HostnameReader(hfd, csvResHandler.getCSVFileHandler());
        VexigoCallOps vco = new VexigoCallOps(hfd);
        Thread producer = new Thread(hr);
        Thread consumer1 = new Thread(vco);
        Thread consumer2 = new Thread(vco);
        producer.setName("Producer");
        producer.start();
        consumer1.setName("Consumer1");
        consumer2.setName("Consumer2");
        consumer1.start();
        consumer2.start();
    }
}
Shades88
  • 7,934
  • 22
  • 88
  • 130

2 Answers2

17

You can't compare strings using ==. You have to use equals.

Read more at What's the difference between ".equals" and "=="?

Community
  • 1
  • 1
Adam Sznajder
  • 9,108
  • 4
  • 39
  • 60
  • that was like freakin amazing!! But can you please explain me again how `Equals operator checks only if references point to the same object (it checks shallow copy)`? I have stored value of `Thread.currentThread().getName()` in a variable. And I am using `==` with a string then how come it outputs false?' – Shades88 Jun 28 '12 at 10:46
  • Post was edited by Reddy. He gave a link where you can find more information. – Adam Sznajder Jun 28 '12 at 10:48
  • because when you say `"Consumer 2"` you're referring to string literal. And the thread name is not it the string literal pool. if you do `threadName.intern();` they will be equal with the `==` operator as well. That is the output will be `true` – ant Jun 28 '12 at 10:49
0

Thread doesn't store the string of the name of the thread. Its stores the name as a char[] so every time you call getName() you actually get a different object.

Thread t = Thread.currentThread();
for (int i = 0; i < 10; i++)
    System.out.println(Integer.toHexString(System.identityHashCode(t.getName())));

prints something like

4318f375
1b17a8bd
2e471e30
3f0ef90c
7000a32b
39d8957f
3a3ee284
768965fb
36867e89
37dd7056

Why doesn't it store the String given in setName I don't know. I assume its for historical reasons.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130