2012-05-01 4 views
6

종종 큰 컬렉션이나 문자열 배열을 인코딩하거나 디코딩해야합니다. 정적 URLDecoder.decode (문자열, "UTF-8")를 사용하여 반복 작업을 수행하는 것 외에도 이러한 유형의 작업을보다 효율적으로 수행 할 수있는 라이브러리가 있습니까?문자열 컬렉션에 대한 URL 인코딩/디코딩을 처리 할 공통 Java 라이브러리가 있습니까?

동료는 정적 메서드를 사용하여 현재 위치에서 문자열을 디코딩하는 것이 스레드로부터 안전하지 않다고 주장합니다. 왜 그랬을까요?

+0

정적 메서드가 URLDecoder 클래스의 정적 변수에 의존하지 않는 한 각 메서드 호출은 스택에서 별도로 진행되며 스레드로부터 안전합니다. URLDecoder.decode (...)가 공유 리소스에 액세스해야하는 이유가 없습니다. – Thomas

답변

7

를 반복 건의 할 것입니다. 특히, 내부적으로는 StringBuffer (URLDecoder의 경우 불필요하게 동기화를 도입 함)에 의존합니다. Apache commons는 URLCodec을 제공하지만 성능과 관련하여 유사한 문제가있는 것으로보고되었지만 가장 최신 버전에서는 여전히 그 사실을 확인하지 않았습니다.

Mark A. Ziesemer은 URLDecoder를 사용하여 문제와 성능에 관한 게시물을 잠시 후 작성했습니다. 그는 몇몇 버그 리포트를 기록하고 완전한 대체물을 작성했습니다. 이 SO이기 때문에, 여기 몇 가지 주요 발췌 인용 것입니다,하지만 당신은 정말 여기에 전체 소스 문서를 읽어야 http://blogger.ziesemer.com/2009/05/improving-url-coder-performance-java.html

선정 따옴표 :

자바 자바에서이 기능의 기본 구현을 제공합니다 .net.URLEncoder 및 java.net.URLDecoder. 불행히도, 구현 내에서 API가 작성된 방법과 세부 정보로 인해 가장 좋은 수행 결과는 이 아닙니다. URLEncoder와 관련하여 성능 관련버그가 sun.com에 접수되었습니다.

대안이 있습니다 : org.apache.commons.codec.net.URLCodec from Apache Commons Codec. (Commons Codec은 또한 Base64 인코딩에 유용한 구현을 제공합니다.) 불행히도 Commons의 URLCodec 은 Java의 URLEncoder/URLDecoder와 동일한 문제를 겪고 있습니다.

...모두 JDK 및 가공에 대한

권장 사항 :

구성 할 때 "버퍼"클래스의, 예를 들어, ByteArrayOutputStream, CharArrayWriter, StringBuilder 또는 StringBuffer, 예상 용량을 예상하고 전달합니다. JDK의 URLEncoder는 현재 StringBuffer에 대해이 작업을 수행하지만 CharArrayWriter 인스턴스에 대해서도 this를 수행해야합니다. Common의 URLCodec 은 ByteArrayOutputStream 인스턴스에 대해이 작업을 수행해야합니다. 클래스의 ' 기본 버퍼 크기가 너무 작은 경우 을 새롭고 더 큰 버퍼로 복사하여 크기를 조정해야 할 수 있습니다. 이는 "값싼"작업이 아닙니다. 클래스의 기본 버퍼 크기가 너무 큰 경우 메모리가 불필요하게 낭비 될 수 있습니다.

모두 구현이 캐릭터 세트에 의존하고 있지만 자신의 문자열 이름으로 그들을 동의합니다. Charset은 이름 검색을 위해 간단하고 작은 캐시를 제공합니다. 사용 된 마지막 2 개의 Charsets 만 저장합니다. 이것은 에 의존해서는 안되며, 둘 다 다른 상호 운용성 이유로 Charset 인스턴스를 받아 들여야합니다.

두 구현은 고정 크기 입력 및 출력 만 처리합니다. JDK의 URLEncoder는 String 인스턴스에서만 작동합니다. Commons의 URLCodec 도 Strings를 기반으로하지만 byte [] 배열에서도 작동합니다. 이는 더 큰 또는 가변 길이 입력의 효율적인 처리 을 본질적으로 방해하는 설계 수준 제약 조건 인 입니다. 대신, CharSequence, Appendable 및 java.nio의 Buffer ByteBuffer 및 CharBuffer 구현과 같은 "스트림 지원" 인터페이스를 지원해야합니다.

...

com.ziesemer.utils.urlCodec가 최대한 빨리 JDK URLEncoder로 3 배 이상주의, 이상 1.5 배 빠른 JDK URLDecoder있다. 합니다 (JDK의 URLDecoder 빠르게 URLEncoder에 비해, 그래서 개선을위한 많은 여지가 없었다.)

내가 당신의 동료가 URLDECODE는 스레드로부터 안전하지 않습니다 제안 할 잘못된 생각합니다. 여기에 대한 다른 해답이 자세하게 설명되어 있습니다.

EDIT [2012-07-03] - 당신이 더 많은 아이디어 여부를 찾고 있다면

확실하지 OP에 의해 게시 후 주석 당? 목록에서 원자 집합으로 작업하려는 경우 메서드 외부의 참조를 포함하여 목록에 대한 모든 액세스를 동기화해야합니다. 그러나 반환 된 목록의 내용이 잠재적으로 다음 원래 목록이 같은 것을 볼 수 있었다 다른 스레드에 의해 수정 될 수있는 컬렉션에서 문자열 "배치"에 운영에 대한 무력 접근 방식에서 각기 다른 괜찮 경우 :

/** 
* @param origList will be copied by this method so that origList can continue 
*     to be read/write by other threads. 
* @return list containing decoded strings for each entry that was 
      in origList at time of copy. 
*/ 
public List<String> decodeListOfStringSafely(List<String> origList) 
     throws UnsupportedEncodingException { 
    List<String> snapshotList = new ArrayList<String>(origList); 
    List<String> newList = new ArrayList<String>(); 

    for (String urlStr : snapshotList) { 
     String decodedUrlStr = URLDecoder.decode(urlStr, "UTF8"); 
      newList.add(decodedUrlStr); 
    } 

    return newList; 
} 

그다지 도움이되지 않는다면, 나는 아직도 당신이 무엇인지 확신 할 수 없으므로 새롭고보다 간결한 질문을 만드는 것이 더 나을 것입니다. 그것이 당신이 묻고있는 것이라면, 여러 가지 이유로 컨텍스트에서 벗어난 예제가 좋은 아이디어가 아니므로 조심하십시오.

+0

감사합니다. 아마도 이것을 두 개의 분리 된 질문으로 분리해야 할 것입니다. 하나는 전체 콜렉션 또는 문자열 배열을 인코딩/디코딩하는 자바 라이브러리에 관한 것이고 하나는 스레드 안전 문제에 관한 것입니다. WRT Apache의 URLCodec은 한 번에 하나의 문자열이나 객체에서만 작동하는 것으로 보입니다. 성능 비교는 유용하다는 것을 보여줍니다. – jrws

+0

WRT 스레드 안전성 문제, 더 많은 컨텍스트를 제공 했어야합니다 (또는 다른 질문을 위해 문제를 남겨 두었습니다. 멍청한 일을 용서해주십시오). 지금까지와 같이 값의 적절한 대체를 수행하는 콜렉션이 메소드 인수 인 public thread (List strings) 때문에 스레드 안전 문제가 발생했습니다. 컬렉션 자체는 값에 의해 호출되지만 참조하는 개체는 여전히 개체에 대한 참조이므로이 컬렉션의 호출자 사용을 제어 할 수 없으므로 동기화가 가장 안전한 작업임을 알리는 것 같습니다. 이것과 같은 것 ... – jrws

+0

... public foo (List strings) {리스트 decodedStrings = Collections. synchronizedList (문자열); – jrws

0

아파치는 디코딩 인코딩에 사용될 수있는 URLCodec을가집니다.

정적 메서드가 로컬 변수 또는 최종 초기화 된 변수에서 작동하는 경우 완전히 스레드 안전합니다.

매개 변수가 스택에서 살아 있고 완전히 스레드 안전성을 갖기 때문에 최종 상수는 변경할 수 없으므로 변경할 수 없습니다. 마지막 변수는 당신이 그것을 다시 할당 할 수없는 의미를 변경할 수있는 경우

public static String encodeMyValue(String value){ 
    // do encoding here 
} 

케어주의해야하지만 내부 표현 (속성)를 변경할 수 있습니다 :

다음 코드는 완전히 스레드로부터 안전합니다.

0

실 안전성은 실제로 정적 함수에서는 절대 필요하지 않습니다 (또는 설계 오류 임). 특히 클래스의 정적 변수에 액세스하지 않는 경우 특히 그렇습니다.

나는 당신이 전에 사용되는 기능을 사용하고, JDK URLDecoder 효율적으로 구현되지 않은 컬렉션

0

기본적으로 정적 메서드 나 인스턴스 메서드 또는 생성자에 적용되는 마법 스레드 안전성은 없습니다. 동기화가 적용되지 않으면 여러 스레드에서 동시에 호출 될 수 있습니다. 공유 데이터를 가져 오거나 변경하지 않으면 일반적으로 안전합니다. 공유 데이터에 액세스하는 경우 더주의해야합니다.

그래서 urldecoding이나 인코딩을 통해 동기화 된 메서드를 작성하여 스레드 안전성을 외부 적으로 강화할 수 있습니다.