Потоковая безопасность использования ссылки forEach l oop в потоке - PullRequest
0 голосов
/ 29 января 2020

Предположим, у меня есть эти коды:

for(File file : fileList) {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            final File fileInThread = file;
            // doing some tasks which may take 5 sec to execute
        }
    });
    thread.start();
}

Что я хочу знать, это потокобезопасно? Есть ли вероятность того, что в первой итерации я ожидаю файл первой итерации, но он инициализируется файлом любой другой итерации l oop? В таком случае, что я могу сделать, чтобы справиться с этой ситуацией?

Мне нужно отправить каждый файл в отдельную ветку. Для каждого файла будет создан один поток. Заранее спасибо.

РЕДАКТИРОВАТЬ: Я также читал эту ветку ... Улучшено 'для' l oop и лямбда-выражений Этот вопрос совершенно другой от моего.

1 Ответ

2 голосов
/ 29 января 2020

Вот что происходит на каждой итерации вашего for(...) l oop:

  1. Локальная переменная file назначается для ссылки на следующий элемент в данном fileList.
  2. Лямбда-выражение создает новый экземпляр анонимного класса Runnable, а лямбда захватывает значение переменной file.
  3. Новый Thread() создается и запускается с использованием анонимного объекта Runnable в качестве своего делегата.

На каждой последующей итерации l oop, другого экземпляра анонимного класса создается, и каждый из этих экземпляров получает различное значение file.

Когда эти потоки запускаются, каждый анонимный Runnable объект будет иметь свое собственное, отдельное захваченное значение для file.


В декларации final File fileInThread = file; нет необходимости. Когда метод run() вызывается для каждого из различных анонимных объектов, file будет ссылаться на захваченное значение , которое будет различным членом списка в каждом потоке.

Переменная final fileInThread будет просто другим именем для того же экземпляра File, на который ссылается file. Опять же, отличается в каждом из потоков.


D'Oh! Я сказал «лямбда» в моем описании выше, но фактический аргумент Thread() конструктор не является лямбда-выражением. Это экземпляр анонимного внутреннего класса. Аналогичная идея, но в ней используется более старый, более подробный синтаксис.

...