java - Lambda 表达式中的 "Starting new Thread in constructor"警告 (NetBeans IDE)

标签 java netbeans lambda thread-safety

当我在传统构造函数中启动新线程时,NetBeansIDE 不会发出警告:

addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {

        (new SomeThread()).start();
    }
});

但是如果我将其转换为 Lambda 表达式,我会收到警告“在构造函数中启动新线程”:

addActionListener((ActionEvent e) -> {

   (new SomeThread()).start();
});

这里有什么问题吗?正确的解决方案是什么?

编辑1:

NetBeans IDE 8.0.2 上出现同样的问题:

enter image description here

代码:

import java.awt.event.ActionEvent;
import javax.swing.Timer;

public class TimerClass extends Timer {

    public TimerClass() {
        super(1000, null);//Loop 1 sec

        addActionListener((ActionEvent e) -> {

            (new SomeClass()).start();
        });

    }

    private class SomeClass extends Thread {

        @Override
        public void run() {

        }
    }
}

最佳答案

这里的问题是,在构造函数中启动线程甚至注册监听器都被认为是危险的。

说明:
内部类包含对其封闭类的引用,这意味着您在构造函数中启动的线程具有对构造函数返回之前 TimerClass 对象状态的引用。因此,新线程可能会看到一个部分构造的对象,其值已过时(在一个线程中是当前值,但在其他线程中不是当前值)。

一个简单的修复:
将构造函数设为私有(private),然后创建一个公共(public)的静态工厂方法来创建对象并启动线程。

import java.awt.event.ActionEvent;
import javax.swing.Timer;

public class TimerClass extends Timer {

    // notice that the constructor is now private.
    private TimerClass() {
        super(1000, null);  //Loop 1 sec
    }

    // This will create the instance and then register the listener and start the thread
    public static TimerClass createInstance() {

        TimerClass instance = new TimerClass();       
        instance.addActionListener((ActionEvent e) -> {

            (instance.new SomeClass()).start();
        });

        return instance;
    }

    private class SomeClass extends Thread {

        @Override
        public void run() {

        }
    }
}

这样,线程将看到一个完全构造的对象,并且线程安全性将被恢复(从而消除警告)。

关于java - Lambda 表达式中的 "Starting new Thread in constructor"警告 (NetBeans IDE),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28924678/

相关文章:

java - 如何将 CardLayout 与 Netbeans GUI Builder 一起使用

python - 如何在 Lambda 中阅读或解释 Lambda

java - 使用Java将Java项目导入到Eclipse中

java - 运行java管道到mutt

javafx声音/视频播放

java - 清理、构建和构建之间的区别?

java - 访问父类子类中静态类的 protected 成员

css - NetBeans jqGrid CSS 问题

c++ - 如何动态地用虚方法实现类

java - 用于消除 if 的 Lambda 用法