Java 从线程访问volatile字段失败
我有一个嵌套线程在循环中运行。它定期访问基类(侦听器)的字段。此字段可以通过setter不时更改。但是,线程只读取第一个赋值。如果我声明该字段为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
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
。