“Starting new Thread in constructor” warning in Lambda expression (NetBeans IDE)

爷,独闯天下 提交于 2021-02-08 07:34:20

问题


When I start new thread in traditional constructor, NetBeansIDE gives no warnings:

addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {

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

But if I convert it to Lambda expression, I'm getting a warning "Starting new Thread in constructor":

addActionListener((ActionEvent e) -> {

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

What is the problem here? What is the correct solution?

EDIT 1:

The same problem on NetBeans IDE 8.0.2:

enter image description here

The code:

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

        }
    }
}

回答1:


The problem here is that it's considered dangerous to start a thread or even register a listener in a constructor.

Explanation:
An inner class contains a reference to its enclosing class meaning that the thread that you started in your constructor has a reference to the TimerClass object's state before the constructor returned. So the new thread might see a partially constructed object with stale values (values that are current in one thread but not for others).

A simple fix:
Make the constructor private and then make a public and static factory method that creates the object and starts the thread.

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

        }
    }
}

With this, the thread will see a fully constructed object and thread safety will be restored (thus removing the warning).



来源:https://stackoverflow.com/questions/28924678/starting-new-thread-in-constructor-warning-in-lambda-expression-netbeans-ide

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!