последнее ключевое слово в параметрах метода не изменяется - PullRequest
0 голосов
/ 10 мая 2019

У меня есть несколько вопросов о финале.Код выглядит следующим образом:

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();
    }
}

вывод:

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

почему?Я думаю, что это выглядит примерно так

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

Ответы [ 3 ]

1 голос
/ 10 мая 2019

Вы определяете свой Thread объект один раз.Это единственный экземпляр, который используется с каждым последующим вызовом вашего fun метода. Это не имеет ничего общего с тем фактом, что url равен final

Если вы измените реализацию вашего метода на что-то вроде этого (сделав thread переменную локальной области видимости),вы увидите, что вы получите ожидаемый результат:

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

Другими словами, когда вы создаете объект Thread, он запоминает значение url, которое было ему передано.И поскольку вы НЕ создаете другие объекты Thread, когда параметр url принимает другое значение, вы можете видеть только значение url, которое было передано при создании объекта, что объясняет, почему вы видите url-0 каждыйвремя.

1 голос
/ 10 мая 2019

Это ключевое слово final в параметре не имеет ничего общего с тем, что вы наблюдаете.

Что в действительности происходит здесь: вы создаете один объект потока, который является экземпляром анонимного внутреннего sub класса Thread. И этот экземпляр получает URL-0 в качестве параметра. Затем после этого вы вызываете метод run() этого одного объекта Thread 4 раза. Таким образом, один и тот же объект печатает одну и ту же строку 4 раза.

Чтобы быть более точным:

  • при первом вводе fun() статическое поле thread равно нулю
  • поэтому создается новый экземпляр, и входящая строка копируется в контекст этого (подкласса Thread) объекта. Эта строка "url-0"
  • затем вы вызываете run () для этого объекта 4 раза

И, как указано в комментариях: простой вызов run() для объекта потока не приводит к тому, что реальный поток ОС работает параллельно. Вы должны позвонить start() вместо этого. Но, конечно, абсолютно бессмысленно повторно вызывать start() для одного и того же потока.

Итак, чтобы ваш код делал больше, чем вы ожидаете, попробуйте следующее:

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();
  }       
}
0 голосов
/ 10 мая 2019

Вы не получаете ожидаемый вывод, потому что вы создаете экземпляр Thread only один раз с первым аргументом 'url-0' .Затем каждый раз, когда вы вызываете метод fun, вы просто вызываете метод, запущенный в единственном созданном потоке thread.run () с аргументом 'url-0'

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...