Java
 Computer >> コンピューター >  >> プログラミング >> Java

JavaのMatcherクラスはスレッドセーフ?マルチスレッド利用時の注意点を解説

正規表現とは、特殊な構文で記述されたパターンをもとに、特定の文字列や文字列の集合を照合・検索するための仕組みです。テキストやデータの検索、編集、加工など、さまざまな場面で活用されています。Javaでは、java.util.regex パッケージによって正規表現によるパターンマッチング機能が提供されています。

Matcherクラスとは

Matcherオブジェクトは、パターンを解釈し、入力文字列に対してマッチング操作を実行する「エンジン」の役割を担うクラスです。Patternクラスと同様に、Matcherクラスには公開されたコンストラクタは用意されておらず、Patternオブジェクトの matcher() メソッドを呼び出すことで取得します。

このクラスのインスタンスは、複数のスレッドから同時に使用することはできません(スレッドセーフではありません)。

つまり、複数のスレッドで同じMatcherインスタンスを共有すると、予期しない動作や誤ったマッチング結果を招く恐れがあります。マルチスレッド環境で正規表現を使用する場合は、次のいずれかの対策が必要です。

  • 各スレッドごとに個別のMatcherオブジェクトを生成して使用する
  • どうしても共有したい場合は、同期(synchronized)処理で排他制御を行う

一方で、Patternクラス自体は不変(イミュータブル)であり、スレッドセーフであることが保証されています。そのため、Patternオブジェクトは複数のスレッド間で安全に共有でき、Matcherだけをスレッドごとに作り直すのが一般的な設計手法です。

サンプルプログラム

次のJavaプログラムは、ユーザーから5つの文字列を入力として受け取り、その中から数字で始まる文字列だけを出力する例です。

import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StartingwithDigit {
    public static void main( String args[] ) {
        String regex = "^[0-9].*$";
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter 5 input strings: ");
        String input[] = new String[5];
        for (int i=0; i<5; i++) {
            input[i] = sc.nextLine();
        }
        // Patternオブジェクトの生成
        Pattern p = Pattern.compile(regex);
        System.out.println("Strings starting with digits: ");
        for(int i=0; i<5;i++) {
            // Matcherオブジェクトの生成
            Matcher m = p.matcher(input[i]);
            if(m.matches()) {
                System.out.println(m.group());
            }
        }
    }
}

実行結果

Enter 5 input strings:
sample string 1
sample string 2
11 sample string 3
22 sample string 4
43534 56353 636
Strings starting with digits:
11 sample string 3
22 sample string 4
43534 56353 636

このように、ループ内で毎回新しいMatcherオブジェクトを生成しているため、単一スレッドでは問題なく動作します。ただし、このMatcherインスタンスを複数スレッドで使い回すことは避け、必要に応じてスレッドごとに生成するようにしましょう。


  1. Javaの正規表現を使って文字列からHTMLタグを抽出する方法

    Javaのjava.util.regexパッケージには、文字シーケンスの中から特定のパターンを検索するためのさまざまなクラスが用意されています。 このパッケージのPatternクラスは、正規表現をコンパイルした結果を表すクラスです。文字列と正規表現のマッチングを行うために、次の2つのメソッドが提供されています。 compile() − 正規表現を表す文字列を引数として受け取り、Patternクラスのオブジェクトを返します。 matcher() − 対象となる文字列を受け取り、その文字列を現在のPatternオブジェクトが表すパターンと照合するためのMatcherオブジェクトを生成します。

  2. Javaの正規表現で文字列から数値を抽出する方法

    Javaの正規表現(Regular Expression)を使えば、文字列の中から数値だけを簡単に取り出すことができます。この記事では、実際のコード例とともに、さまざまなパターンでの数値抽出の方法を解説します。文字列を解析し、必要な情報を抜き出すスキルは、テスターにとって欠かせない能力の一つです。特にAPIテストでは、JSONやXML形式のレスポンスを解析する場面が多く、正規表現の知識が大いに役立ちます。以下では、Javaの正規表現を使って文字列から数字・数値を抽出する具体的な例を紹介します。文字列からすべての数値を抽出するimport java.util.regex.Matcher; imp