这是我第一次遇到像下面这样的事情。
多个线程(实现 Runnable 的内部类)共享一个数据结构(上层类的实例变量)。
工作:从 Eclipse 项目的 bin 文件夹中获取类,在 Unix 机器上运行。
不工作:直接在 Unix 机器上编译 src 并使用那些类文件。代码编译然后运行,没有错误/警告,但一个线程无法正确访问共享资源。
问题:一个线程将元素添加到上述常见的 DS 中。第二个线程执行以下操作...
while(true){ if(myArrayList.size() > 0){ //do stuff }
}
日志显示大小在线程 1 中更新。
出于某种神秘的原因,工作流程没有进入 if() ...
如果我直接从 Eclipse 的 bin 文件夹中粘贴类文件,完全相同的代码可以完美运行。
如果我错过了任何明显的东西,我深表歉意。
代码:
ArrayList<CSRequest> newCSRequests = new ArrayList<CSRequest>();
//线程1
private class ListeningSocketThread implements Runnable {
ServerSocket listeningSocket;
public void run() {
try {
LogUtil.log("Initiating...");
init(); // creates socket
processIncomongMessages();
listeningSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void processIncomongMessages() throws IOException {
while (true) {
try {
processMessage(listeningSocket.accept());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
private void processMessage(Socket s) throws IOException, ClassNotFoundException {
// read message
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
Object message = ois.readObject();
LogUtil.log("adding...: before size: " + newCSRequests.size());
synchronized (newCSRequests) {
newCSRequests.add((CSRequest) message);
}
LogUtil.log("adding...: after size: " + newCSRequests.size()); // YES, THE SIZE IS UPDATED TO > 0
//closing....
}
........
}
//Thread 2
private class CSRequestResponder implements Runnable {
public void run() {
LogUtil.log("Initiating..."); // REACHES..
while (true) {
// LogUtil.log("inside while..."); // IF NOT COMMENTED, FLOODS THE CONSOLE WITH THIS MSG...
if (newCSRequests.size() > 0) { // DOES NOT PASS
LogUtil.log("inside if size > 0..."); // NEVER REACHES....
try {
handleNewCSRequests();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
....
}
更新
解决方案是在我检查线程 2 中的大小之前添加 synchronized(myArrayList)。