The server is initialized then thread started. The thread writes to List<String> JSON_LIST
. When http request comes to parent thread it shows that JSON_LIST
is empty however other thread have already added new element. Why volatile is not working?
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");
}
UPDATE
I have one class. It should acts as web server. Additional theread was created to populate JSON_LIST with records. The problem is when I try to return JSON_LIST.get(JSON_LIST.size() - 1)
it always returns ArrayindexOutOfBound exception. Therefore, Jersey thread cannot see updates made to private volatile List<String> JSON_LIST
.
How to fix it?
UPDATE2:
I have tried several things:
private volatile CopyOnWriteArrayList<String> JSON_LIST = new CopyOnWriteArrayList<String>();
and
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);
}
}
Nothing solved the problem
Because volatile only guarantees the visibility of a new value of JSON_LIST. Ie, it guarantees that, if you assign a new list to the JSON_LIST variable in thread A, thread B will see the new value of the variable.
Changes to the list referenced by the variable are not made thread-safe by volatile. You need a thread-safe list to have such a guarantee, or you need to synchronize every access to the list.
EDIT:
reading your code again, this seems more than a concurrency problem. Jersey doesn't use the same HelloWorld instance than the one you explicitely create and start in your main method. So your main method adds in a list, and Jersey reads in another one.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.