有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案

  1. # 1 楼答案

    因为volatile只保证JSON_LIST的新值的可见性。也就是说,它保证,如果在线程a中为JSON_list变量分配一个新列表,那么线程B将看到该变量的新值

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

    编辑:

    再次阅读代码,这似乎不仅仅是一个并发问题。Jersey使用的HelloWorld实例与您在main方法中明确创建并启动的实例不同。因此,您的主方法将添加到一个列表中,Jersey将读取另一个列表