【问题标题】:"Starting new Thread in constructor" warning in Lambda expression (NetBeans IDE)Lambda 表达式中的“在构造函数中启动新线程”警告(NetBeans IDE)
【发布时间】:2015-03-08 08:51:16
【问题描述】:

当我在传统构造函数中启动新线程时,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 上的同样问题:

代码:

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() {

        }
    }
}

【问题讨论】:

  • 看起来像 NetBeans 诊断中的错误。
  • 这只是一个警告,我猜它应该是可配置的(虽然我不确定)。请查看 NetBeans 中的警告配置,您可能会有所发现。
  • 是的,但一定是这个原因..
  • 原因是显示“在构造函数中启动新线程”警告的 NetBeans 代码是在 Java 8 存在之前编写的,并且在向 NetBeans 添加对 Java 8 语法的支持时没有正确更新。
  • 是的,可能是这样,因为我使用的是 NetBeans 7.4,所以我会在 8.0.2 上尝试并通知您。

标签: java netbeans lambda thread-safety


【解决方案1】:

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

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

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

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() {

        }
    }
}

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

【讨论】:

    猜你喜欢
    • 2015-09-06
    • 2013-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-19
    • 1970-01-01
    相关资源
    最近更新 更多