Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从线程访问volatile字段失败_Java_Multithreading_Field_Volatile - Fatal编程技术网

Java 从线程访问volatile字段失败

Java 从线程访问volatile字段失败,java,multithreading,field,volatile,Java,Multithreading,Field,Volatile,我有一个嵌套线程在循环中运行。它定期访问基类(侦听器)的字段。此字段可以通过setter不时更改。但是,线程只读取第一个赋值。如果我声明该字段为volatile,它不会改变任何内容 有人知道这里可能出了什么问题吗 下面是代码的摘录,其中包含重要部分: public class GameClient implements Parcelable { private SocketWrapper socket; private String nickname; private

我有一个嵌套线程在循环中运行。它定期访问基类(侦听器)的字段。此字段可以通过setter不时更改。但是,线程只读取第一个赋值。如果我声明该字段为volatile,它不会改变任何内容

有人知道这里可能出了什么问题吗

下面是代码的摘录,其中包含重要部分:

public class GameClient implements Parcelable {

    private SocketWrapper socket;
    private String nickname;
    private String roomName;
    private boolean isConnected;

    **private volatile GeneralGameListener listener;**

    [...]

    /**
     * Starts the thread to receive messages from the server.
     * Needs a Listener to be set via registerListener() first.
     */
    public void startReceiveLoop() {
        if(!isConnected) {
            throw new RuntimeException("The client is not connected to any room");
        }

        new Thread(() -> {
            while (true) {
                try {
                    String fromServer = socket.readString();
                    String[] params = fromServer.split("\\s");
                    switch (params[0]) {
                        [...]
                        case "begin_puzzle":
                            long finishUntil = Long.parseLong(params[1]);

                            if(getListener() instanceof InRoundListener)
                                **((InRoundListener) listener.beginPuzzle(finishUntil);**
                            break;
                        [...]
                        default:
                            listener.unknownMessage(fromServer);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /**
     * Sets a Listener to listen for messages from the server.
     * Only one listener can be registered at a time so this overwrites any previously registered Listener.
     * @param listener the Listener to be registered
     */
    public void registerListener(GeneralGameListener listener) {
        this.listener = listener;
    }

}

您是否尝试了一个
AtomicReference
,而不仅仅是一个volatile字段?无论何时调用registerListener,还是从线程内部(getListener()?),您都可以通过打印侦听器的标识(例如System.identityHashCode或更具体的标识,如果您得到了该标识)来开始调试请注意,您应该只获得一次侦听器。在上面的代码中,您得到了三次,每次都可以在多线程环境中返回不同的结果。您可能希望重新设计该类并将所有侦听器放在一个映射中,替换开关,从映射中获取所需的侦听器。另外请注意:该字段不是侦听器。您的
GameClient
listener
字段是
volatile
,但这并不意味着listener对象的字段是
volatile