初始化服务器然后启动线程。该线程写入List<String> JSON_LIST
。当http请求到达父线程时,它显示JSON_LIST
为空,但其他线程已添加新元素。为什么挥发性不起作用?
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服务器。创建了附加组件以使用记录填充JSON_LIST。问题是,当我尝试return JSON_LIST.get(JSON_LIST.size() - 1)
时,它总是返回ArrayindexOutOfBound异常。因此,Jersey线程无法查看对private volatile List<String> JSON_LIST
所做的更新。
如何解决?
UPDATE2:
我尝试了几件事:
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);
}
}
没有解决问题
答案 0 :(得分:1)
因为volatile只保证JSON_LIST新值的可见性。即,它保证,如果为线程A中的JSON_LIST变量分配新列表,则线程B将看到变量的新值。
变量引用的列表的更改不会因volatile而成为线程安全的。您需要一个线程安全列表才能获得此类保证,或者您需要同步对列表的每次访问。
编辑:
再次阅读您的代码,这似乎不仅仅是一个并发问题。 Jersey不使用与您明确创建并在main方法中启动的HelloWorld实例相同的HelloWorld实例。所以你的main方法会添加一个列表,而Jersey会读入另一个。