답변:
예 , Pattern 클래스에 대한 Java API 문서에서
이 (Pattern) 클래스의 인스턴스는 변경할 수 없으며 여러 동시 스레드에서 사용하기에 안전합니다. Matcher 클래스의 인스턴스는 이러한 사용에 안전하지 않습니다.
성능 중심 코드를보고있는 경우 새 인스턴스를 만드는 대신 reset () 메서드를 사용하여 Matcher 인스턴스를 재설정하십시오. 이렇게하면 Matcher 인스턴스의 상태가 재설정되어 다음 정규식 작업에 사용할 수 있습니다. 실제로 동시 액세스에 대해 안전하지 않은 것은 Matcher 인스턴스에서 유지되는 상태입니다.
요약:
Java 정규식 API는 여러 일치 작업에서 단일 컴파일 된 패턴을 공유 할 수 있도록 설계되었습니다.
다른 스레드에서 동일한 패턴에 대해 Pattern.matcher () 를 안전하게 호출 하고 동시에 매처를 안전하게 사용할 수 있습니다. Pattern.matcher () 는 동기화없이 매처를 생성하는 것이 안전합니다. 메서드가 동기화되지는 않지만 Pattern 클래스 내부에 있지만, 패턴을 생성 한 후에는 항상 compile이라는 휘발성 변수가 설정되고 matcher () 호출이 시작될 때 읽습니다 . 이렇게하면 Pattern을 참조하는 모든 스레드가 해당 개체의 내용을 올바르게 "볼"수 있습니다.
반면에 서로 다른 스레드간에 Matcher를 공유해서는 안됩니다. 또는 적어도 그렇게했다면 명시 적 동기화를 사용해야합니다.
스레드 안전성은 주변 코드도 고려해야한다는 것을 기억해야하지만 운이 좋은 것 같습니다. 사실 매처 (Matchers)이 패턴의 사용하여 만들어집니다 정규의 팩토리 메소드와 public 생성자 부족은 긍정적이다. 마찬가지로 컴파일 정적 메서드를 사용하여 포함하는 패턴 을 만듭니다. .
간단히 말해 예와 같은 작업을 수행하면 다음과 같습니다.
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();
당신은 꽤 잘하고 있어야합니다.
명확성을 위해 코드 예제에 대한 후속 조치 :이 예제는 이렇게 생성 된 Matcher가 Pattern 및 테스트와 함께 스레드 로컬임을 강력하게 암시합니다. 즉, 이렇게 생성 된 Matcher를 다른 스레드에 노출해서는 안됩니다.
솔직히 이것은 스레드 안전성 질문의 위험입니다. 현실은 충분히 노력하면 모든 코드가 스레드에 안전하지 않게 될 수 있다는 것입니다. 다행히도 우리가 코드를 망칠 수있는 모든 방법을 가르쳐주는 멋진 책 들이 있습니다. 이러한 실수를 피하면 스레딩 문제가 발생할 가능성이 크게 줄어 듭니다.
에 대한 코드를 간략히 살펴보면 Matcher.java
일치하는 텍스트, 그룹 배열, 위치 유지 관리를위한 몇 가지 인덱스, boolean
다른 상태를위한 몇 가지를 포함하는 여러 멤버 변수가 표시 됩니다. 이 모든 Matcher
것은 다중에서 액세스 할 경우 제대로 작동하지 않는 상태 저장 을 가리 킵니다 Threads
. JavaDoc도 마찬가지입니다 .
이 클래스의 인스턴스는 여러 동시 스레드에서 사용하기에 안전하지 않습니다.
@Bob Cross가 지적했듯이 Matcher
별도 Thread
의 s 에서 사용을 허용하는 경우에만 문제가됩니다 . 이 작업을 수행해야하고 코드에서 동기화가 문제가 될 것이라고 생각하는 경우에는 ThreadLocal
저장소 개체를 사용하여 Matcher
작업 스레드 당 유지 관리 할 수 있습니다.
요약하면, 컴파일 된 패턴을 재사용 (정적 변수에 유지)하고 일부 문자열에 대해 해당 정규식 패턴의 유효성을 검사해야 할 때 새 매처를 제공하도록 지시 할 수 있습니다.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Validation helpers
*/
public final class Validators {
private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})$";
private static Pattern email_pattern;
static {
email_pattern = Pattern.compile(EMAIL_PATTERN);
}
/**
* Check if e-mail is valid
*/
public static boolean isValidEmail(String email) {
Matcher matcher = email_pattern.matcher(email);
return matcher.matches();
}
}
이메일 유효성 검사에 사용 된 RegEx 패턴에 대해서는 http://zoomicon.wordpress.com/2012/06/01/validating-e-mails-using-regular-expressions-in-java/ (끝 근처)를 참조하십시오. 여기에 게시 된대로 이메일 검증을위한 요구 사항에 맞지 않는 경우)
static {}
? 그 변수 초기화를 인라인하고 만들 수도 Pattern
final
있습니다.
private static final Pattern emailPattern = Pattern.compile(EMAIL_PATTERN);
더 낫다.
compile()
메서드는 그렇지 않을 수 있습니다. 멀티 스레드 환경에서 컴파일이 실패하는 원인이 된 버그가 수년 동안 2 ~ 3 개있었습니다. 동기화 된 블록에서 컴파일을 수행하는 것이 좋습니다.