2014-09-09 3 views
0

서버가 초기화 된 후 스레드가 시작되었습니다. 스레드는 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"); 
     } 

UPDATE. 웹 서버로 작동해야합니다. 추가로 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

'HelloWorld' 스레드는 Jersey의 핸들러이기도합니다. 그 메소드에'@ GET'으로 주석을 달았 기 때문에 핸들러가되지 않습니다. 당신이 실제로하고있는 것을 보여주십시오. –

+0

완전히 재현 할 수있는 예를 게시하십시오. 내가 게시 한 코드로 무엇을 시연하려고하는지 알지 못합니다. 나는 당신의 문제가 '휘발성'이라고 생각하지 않습니다. –

답변

1

휘발성은 JSON_LIST의 새로운 값의 가시성을 보장하기 때문에. 즉, 스레드 A의 JSON_LIST 변수에 새 목록을 할당하면 스레드 B는 변수의 새 값을 보게됩니다.

변수가 참조하는 목록의 변경 사항은 volatile에 의해 스레드로부터 안전하지 않습니다. 그러한 보증을 위해서는 스레드 안전 목록이 필요하거나 목록에 대한 모든 액세스를 동기화해야합니다.

편집 :

다시 코드를 읽고, 이것은 동시성 문제보다 더 많은 것 같다. Jersey는 명시 적으로 만들고 Main 메소드에서 시작하는 인스턴스와 동일한 HelloWorld 인스턴스를 사용하지 않습니다. 그래서 당신의 주된 방법은리스트에 추가되고 Jersey는 다른 것을 읽습니다.

+0

예를 들려 줄 수 있습니까? 'addJSONRecord' 메소드 시그니처에'synchronized'를 넣을 수 없으며'JSON_LIST.add (s)'를'synchronized'로 감쌀 수도 없습니다 –

+0

예제는 무엇입니까? –

+0

가장 쉬운 해결책이 필요합니다. –

관련 문제