2009-08-16 2 views
14

나는 쉼표, 수천을 분리하여, 단순히 더 읽기 숫자를 문자열로 변환하는 java.text.NumberFormat의를 사용하는 등 기본적으로 내가로 정의 :Java : NumberFormat과 동기화 문제가 있습니까?

public static NumberFormat nf = NumberFormat.getInstance(Locale.US); 

... 그리고 난 그냥 (nf.format 전화 some_number) 숫자의 읽을 수있는 버전을 만들고 싶은 모든 스레드에서. 그러나 JavaDoc을 보면 "숫자 형식은 일반적으로 동기화되지 않으므로 각 스레드마다 별도의 형식 인스턴스를 만드는 것이 좋습니다. 여러 스레드가 동시에 형식에 액세스하는 경우 외부에서 동기화해야합니다."

NumberFormat 개체의 format (number) 메서드 만 사용하는 경우 동기화 문제가있을 수 있습니까? 대신 NumberFormat.getInstance (Locale.US) .format (number)를 사용하여 시도해 보았습니다.하지만 실제로 필요할 필요가 없을 때마다 그렇게하는 것과 관련된 오버 헤드가 있습니다. 이 작업에 외부 동기화가 필요합니까? 아니면 NumberFormat을 사용하지 않고도 동일한 작업을보다 간단하고 효율적으로 수행 할 수 있습니까?

감사합니다.

답변

15

호출하는 유일한 방법이 포맷이라해도, 여전히 스레드로부터 안전하지는 않습니다. 사실, 우리는 이것 때문에 직장에서 버그를 겪었습니다. 우리는 보통 NumberFormat 객체를 즉시 생성하거나 Gerco가 제안한 ThreadLocal을 사용합니다. 멋진 방법을 원한다면 NumberFormat을 서브 클래스화할 수 있고 format 메서드에서는 대리자 NumberFormat에서 format을 호출하기 전에 동기화하거나 ThreadLocal을 사용하여 대리자를 검색 할 수 있습니다.

그러나 가장 직접적인 방법은 여러 개의 숫자를 연속적으로 형식화/구문 분석하려는 경우 수동으로 ThreadLocal을 사용하는 것입니다.

+0

https://gist.github.com/jontejj/5430320을 사용하여 측정 한 결과는 http://1.microbenchmarks.appspot.com/run/[email protected]/se.softhouse에서 게시됩니다. .common.numbers.NumberFormatBenchmark는 서식 지정 숫자가 유일한 일이면 이득이 실제로 상당히 큽니다. NumberFormat은 생성 된 포맷터에 대한 캐시를 유지하고 반환하기 전에 복제합니다. – jontejj

+0

그리고 똑같은 모든 하위 클래스에 적용됩니다. 특히 DateFormat – Snicolas

8

ThreadLocal을 사용하십시오. <NumberFormat>. 그렇게하면 각 스레드는 자신의 private NumberFormat 인스턴스를 가지므로 동기화 할 필요가없고 최소한의 오버 헤드 만 발생합니다.

1

NumberFormat 개체를 공유 할 이유가 없습니다. 예, 동기화 문제가 발생할 수 있습니다 (로케일의 소스를 살펴보면 형식 변수에도 멤버 변수가 사용됨을 알 수 있습니다). 성능 문제가 발생할 때까지 (대부분은 그렇지 않을 것입니다), 각 용도별로 새로운 성능 문제를 만드십시오.

편집 마이클 Borgwardt가 지적했듯이 멤버 변수에 대한 내 직감이 올바르지 않습니다. 아직도, 왜 걱정하지? LocalThread를 사용하거나 NumberFormat을 복제하거나 새로운 형식을 만듭니다. 객체 생성 측면에서의 효율성은 실제 관심사가 아닙니다 대부분의 경우 (항상 그런 것은 아닙니다).

3

NumberFormatDecimalFormat의 소스 코드를 보면 중간 결과에 사용되는 필드가없는 것 같습니다. 형식 자체 (예 : 소수점 이하 자릿수)는 설정자를 통해 변경할 수 있으므로 스레드는 다른 사람의 format() 호출이 처리되는 동안 그것을 바꿀 수 있으며, 물론 엉망이 될 것입니다.

세터를 절대 사용하지 않으면 이되어야합니다.이되어야합니다. 물론 이것은 현재 구현에 불과합니다. API 문서에 위배되는 경우에 따라 편안하지 않을 것입니다. ThreadLocal을 사용하면 좋은 절충안처럼 들릴 수 있습니다.

+1

저는 이것이 낡은 대답이라는 것을 알고 있습니다. 그러나 ... 당신은 정말로 소스 코드를 사용해서는 안됩니다. 사용중인 Java 버전을 알고 있더라도 공급 업체마다 다릅니다. (예를 들어, IBM과 Sun/Oracle JVM의 차이점을 많이 봤습니다.) –

+0

JDK의 제 버전에는 실제로 중간 결과가 저장되어 있지만 YMMV는 말했습니다. – jontejj

2

NumberFormatabstract class입니다. getInstance을 호출 할 때 기본값은 DecimalFormat의 인스턴스를 반환하는 것입니다.DecimalFormat은 형식화 프로세스 내에서 위치를 유지하기위한 일련의 필드, 접두어 및 접미사 패턴, 지수 표기법 및 수천 그룹화를 사용할지 여부를 나타내는 boolean, 정수 및 소수 부분의 크기를 나타내는 int 등을 사용합니다.

ThreadLocal 옵션은 동시 서식 지정을 원할 경우 가장 좋은 방법입니다. abstractFormat 클래스의 모든 하위 클래스는 스레드로부터 안전하지 않은 것으로 간주되므로 서식 지정 날짜는 이처럼 많은주의를 기울여 처리해야합니다.

관련 문제