无法在使用volatile的线程之间共享List值

时间:2014-09-09 21:42:31

标签: java multithreading jersey webserver

初始化服务器然后启动线程。该线程写入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);
        }
    }

没有解决问题

1 个答案:

答案 0 :(得分:1)

因为volatile只保证JSON_LIST新值的可见性。即,它保证,如果为线程A中的JSON_LIST变量分配新列表,则线程B将看到变量的新值。

变量引用的列表的更改不会因volatile而成为线程安全的。您需要一个线程安全列表才能获得此类保证,或者您需要同步对列表的每次访问。

编辑:

再次阅读您的代码,这似乎不仅仅是一个并发问题。 Jersey不使用与您明确创建并在main方法中启动的HelloWorld实例相同的HelloWorld实例。所以你的main方法会添加一个列表,而Jersey会读入另一个。