Вот что происходит на каждой итерации вашего for(...)
l oop:
- Локальная переменная
file
назначается для ссылки на следующий элемент в данном fileList
. - Лямбда-выражение создает новый экземпляр анонимного класса
Runnable
, а лямбда захватывает значение переменной file
. - Новый
Thread()
создается и запускается с использованием анонимного объекта Runnable
в качестве своего делегата.
На каждой последующей итерации l oop, другого экземпляра анонимного класса создается, и каждый из этих экземпляров получает различное значение file
.
Когда эти потоки запускаются, каждый анонимный Runnable
объект будет иметь свое собственное, отдельное захваченное значение для file
.
В декларации final File fileInThread = file;
нет необходимости. Когда метод run()
вызывается для каждого из различных анонимных объектов, file
будет ссылаться на захваченное значение , которое будет различным членом списка в каждом потоке.
Переменная final fileInThread
будет просто другим именем для того же экземпляра File
, на который ссылается file
. Опять же, отличается в каждом из потоков.
D'Oh! Я сказал «лямбда» в моем описании выше, но фактический аргумент Thread()
конструктор не является лямбда-выражением. Это экземпляр анонимного внутреннего класса. Аналогичная идея, но в ней используется более старый, более подробный синтаксис.