Java 在线程中使用forEach循环引用的线程安全性

Java 在线程中使用forEach循环引用的线程安全性,java,thread-safety,Java,Thread Safety,假设我有以下代码: 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 }

假设我有以下代码:

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();
}
我想知道的是,它是线程安全的吗?有没有可能,在第一次迭代中,我期望的是第一次迭代的文件,但它是由循环的任何其他迭代的文件初始化的?在这种情况下,我能做些什么来处理这种情况

我需要将每个文件发送到不同的线程。对于每个文件,将创建一个线程。提前谢谢


编辑:我也读过这个帖子。。。这个问题与我的问题完全不同。

以下是(…)的
循环每次迭代时发生的情况:

  • 局部变量
    文件
    被指定为引用给定
    文件列表
    中的下一项
  • lambda表达式创建一个匿名的
    Runnable
    类的新实例,lambda捕获
    文件
    变量的值
  • 创建并启动一个新的
    Thread()
    ,使用匿名
    Runnable
    对象作为其委托
  • 在循环的每个后续迭代中,都会创建匿名类的不同实例,并且这些实例中的每个实例都会捕获不同的
    file

    当这些线程运行时,每个匿名
    Runnable
    对象都将有自己的
    文件
    的不同捕获值


    声明,
    final File fileInThread=File不是必需的。当为每个不同的匿名对象调用
    run()
    方法时,
    file
    将引用捕获的值,该值将是每个线程中列表的不同成员

    final fileInThread
    变量将只是
    File
    引用的同一
    File
    实例的另一个名称。同样,每个线程都不同



    哦我在上面的描述中提到了“lambda”,但是
    Thread()
    构造函数的实际参数不是lambda表达式。它是匿名内部类的实例化。类似的想法,但它使用了更老、更详细的语法。

    以下是(…)
    循环的
    每次迭代时发生的情况:

  • 局部变量
    文件
    被指定为引用给定
    文件列表
    中的下一项
  • lambda表达式创建一个匿名的
    Runnable
    类的新实例,lambda捕获
    文件
    变量的值
  • 创建并启动一个新的
    Thread()
    ,使用匿名
    Runnable
    对象作为其委托
  • 在循环的每个后续迭代中,都会创建匿名类的不同实例,并且这些实例中的每个实例都会捕获不同的
    file

    当这些线程运行时,每个匿名
    Runnable
    对象都将有自己的
    文件
    的不同捕获值


    声明,
    final File fileInThread=File不是必需的。当为每个不同的匿名对象调用
    run()
    方法时,
    file
    将引用捕获的值,该值将是每个线程中列表的不同成员

    final fileInThread
    变量将只是
    File
    引用的同一
    File
    实例的另一个名称。同样,每个线程都不同



    哦我在上面的描述中提到了“lambda”,但是
    Thread()
    构造函数的实际参数不是lambda表达式。它是匿名内部类的实例化。类似的想法,但它使用了更旧、更详细的语法。

    使用此代码,每个文件将位于不同的线程中。只是你不能确定第一个文件会在第二个文件之前被处理。这能回答你的问题吗?简短回答:
    for
    循环中的
    file
    变量实际上是最终变量,因此内部Runnable中的值不可能被其他线程更改。@dnault,不是。只需阅读该线程和本线程。它不是final或effectivefinal的情况。看到答案了,我希望你能得到。如果有什么需要补充的,请给出建议@dnaulty使用此代码将每个文件放在不同的线程中。只是你不能确定第一个文件会在第二个文件之前被处理。这能回答你的问题吗?简短回答:
    for
    循环中的
    file
    变量实际上是最终变量,因此内部Runnable中的值不可能被其他线程更改。@dnault,不是。只需阅读该线程和本线程。它不是final或effectivefinal的情况。看到答案了,我希望你能得到。如果有什么需要补充的,请给出建议@D诺顿问题。。在匿名类之外声明并在匿名类中使用的变量是否成为匿名类的字段变量?否则,run()如何记住该线程使用的文件?我是这么说的,随着迭代的进行,文件引用的是不同的文件。若启动线程需要时间,在第二次迭代中,第一个线程可以开始工作。@Mukit09,是的。当您在
    run()
    方法中看到
    file
    时,它引用匿名内部类的隐式字段。该字段初始化为与(…)的
    循环中声明的
    文件
    局部变量具有相同的值。一个问题。。在匿名类之外声明并在匿名类中使用的变量是否成为匿名类的字段变量?否则,run()如何记住该线程使用的文件?我是这么说的,随着迭代的进行,文件引用的是不同的文件。若启动线程需要时间,则在第二次迭代中,第一个线程可以开始工作。@Mukit09