java无法使用volatile在线程之间共享列表值
服务器初始化,然后线程启动。线程写入List<String> JSON_LIST
。当http请求到达父线程时,它显示JSON_LIST
为空,但其他线程已经添加了新元素。为什么volatile不起作用
import com.sun.net.httpserver.HttpServer;
import com.sun.jersey.api.container.httpserver.HttpServerFactory;
import org.codehaus.jackson.map.ObjectMapper;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
public class HelloWorld extends Thread {
@GET
@Produces("text/plain")
public String getClichedMessage() {
// Return some cliched textual content
return JSON_LIST.get(JSON_LIST.size() - 1);
}
private volatile List<String> JSON_LIST = new ArrayList<String>();
public void addJSONRecord(String s){
JSON_LIST.add(s);
}
@Override
public void run() {
addJSONRecord(json);
}
public static void main(String[] args) throws IOException {
HttpServer server = HttpServerFactory.create("http://localhost:8080/");
server.start();
(new HelloWorld()).start();
System.out.println("Server running");
System.out.println("Visit: http://localhost:8080/service");
System.out.println("Hit return to stop...");
System.in.read();
System.out.println("Stopping server");
server.stop(0);
System.out.println("Server stopped");
}
更新
我有一节课。它应该充当web服务器。创建额外的theread以使用记录填充JSON_列表。问题是当我尝试return JSON_LIST.get(JSON_LIST.size() - 1)
时,它总是返回ArrayIndexOutofBond异常。因此,Jersey线程无法看到对private volatile List<String> JSON_LIST
的更新
如何修复它
更新2:
我试过几种方法:
private volatile CopyOnWriteArrayList<String> JSON_LIST = new CopyOnWriteArrayList<String>();
及
public String getClichedMessage() {
synchronized (JSON_LIST){
return JSON_LIST.get(JSON_LIST.size() - 1);
}
}
public void addJSONRecord(String s){
synchronized (JSON_LIST){
JSON_LIST.add(s);
}
}
什么也解决不了问题
# 1 楼答案
因为volatile只保证JSON_LIST的新值的可见性。也就是说,它保证,如果在线程a中为JSON_list变量分配一个新列表,那么线程B将看到该变量的新值
volatile不会使对变量引用的列表所做的更改成为线程安全的。您需要一个线程安全的列表才能获得这样的保证,或者您需要同步对该列表的每次访问
编辑:
再次阅读代码,这似乎不仅仅是一个并发问题。Jersey使用的HelloWorld实例与您在main方法中明确创建并启动的实例不同。因此,您的主方法将添加到一个列表中,Jersey将读取另一个列表