Alex_mahao
Alex_mahao

Reputation: 9

final keyword in method parameters not change

I have some questions about final. The code is as follows

public class Demo {
    private static Thread thread;
    public static void main(String[] args) {
        for (int i = 0; i < 4; i++) {
            fun("url-" + i);
        }
    }
    public static void fun(final String url) {
        if (thread == null) {
            thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(url);
                }
            });
        }
        thread.run();
    }
}

output:

url-0
url-0
url-0
url-0

why? I think it looks something like this

url-1
url-1
url-3
url-4

Upvotes: 0

Views: 60

Answers (3)

Marquise Mery
Marquise Mery

Reputation: 140

You are not getting the expected output because you are instantiating the Thread only once with the first argument 'url-0'. Then, each time you call the method fun, you are just calling the method run on the only one created thread thread.run() with the argument 'url-0'

Upvotes: 0

GhostCat
GhostCat

Reputation: 140427

That keyword final on the parameter has nothing to do with what you observe.

What really happens here: you create one thread object, that is an instance of an anonymous inner subclass of Thread. And that instance gets url-0 as parameter. Then, afterwards, you call the run() method of that one Thread object 4 times. Thus the same object prints the same string 4 times.

To be more precise:

  • the first time you enter fun(), the static thread field is null
  • so a new instance is created, and the incoming string is copied into the context of that (subclass of Thread) object. That string is "url-0"
  • then you call run() on that object 4 times

And as outlined in the comments: just calling run() on a thread object doesn't cause a real OS thread to do work in parallel. You have to call start() instead. But of course, it absolutely makes no sense to call start() repeatedly for the same thread.

So, in order for your code to do more of what you expect, try this:

public class Demo {

  public static void main(String[] args) {
    for (int i = 0; i < 4; i++) {
        fun("url-" + i);
    }
  }
  public static void fun(String url) {
    Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(url);
            }
        });
        thread.start();
  }       
}

Upvotes: 1

ernest_k
ernest_k

Reputation: 45309

You are defining your Thread object once. It's this only instance that's being used with each subsequent invocations of your fun method. This has nothing to do with the fact that url is final

If you change your method implementation to something like this (making thread a local-scoped variable), you'll see that you get the expected output:

public static void fun(String url) {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println(url);
        }
    });
    thread.run();
}

In other words, when you create your Thread object, it remembers the value of url that was passed to it. And because you are NOT creating other Thread objects when the url parameter takes a different value, you can only see the value of url that was passed when the object was created, which explains why you see url-0 every time.

Upvotes: 1

Related Questions