JacksonライブラリのObjectMapper
クラス スレッドセーフのようです 。
これは、ObjectMapper
をこのような静的フィールドとして宣言する必要があることを意味しますか
class Me {
private static final ObjectMapper mapper = new ObjectMapper();
}
このようなインスタンスレベルのフィールドとしてではなく?
class Me {
private final ObjectMapper mapper = new ObjectMapper();
}
はい、それは安全で推奨されます。
参照したページの唯一の注意点は、マッパーが共有されると、マッパーの構成を変更できないことです。ただし、構成を変更していないので問題ありません。設定を変更する必要がある場合は、静的ブロックから変更しますが、それでも問題ありません。
編集:(2013/10)
2.0以降では、さらに良い方法があることに注意することで上記を強化できます:ObjectWriter
とObjectReader
オブジェクトを使用します。これらはObjectMapper
で構築できます。これらは完全に不変で、スレッドセーフです。つまり、理論上、スレッドセーフの問題(コードがインスタンスを再構成しようとするとObjectMapper
で発生する可能性がある)を引き起こすことさえできません。
ObjectMapperはスレッドセーフですが、特にマルチスレッドアプリケーションでは、静的変数として宣言することを強くお勧めします。それが悪い習慣だからでなく、デッドロックの大きなリスクを抱えているからです。私は自分の経験からそれを伝えています。 WebサービスからJSONデータを取得および処理する4つの同一のスレッドを持つアプリケーションを作成しました。スレッドダンプによると、私のアプリケーションは次のコマンドで頻繁に停止していました。
Map aPage = mapper.readValue(reader, Map.class);
それに加えて、パフォーマンスは良くありませんでした。静的変数をインスタンスベースの変数に置き換えたとき、ストールがなくなり、パフォーマンスが4倍になりました。つまり240万件のJSONドキュメントが、2.5時間前ではなく40分56秒で処理されました。
スレッドの安全性の観点から静的ObjectMapperを宣言することは安全ですが、Javaで静的オブジェクト変数を構築することは悪い習慣と見なされることに注意する必要があります。詳細については、「 なぜ静的変数が悪と見なされるのか? 」(および、必要に応じて、 my answer )を参照してください。
要するに、簡潔な単体テストを書くのが難しくなるので、静的なものは避けるべきです。たとえば、静的な最終ObjectMapperを使用すると、JSONシリアル化をダミーコードまたはノーオペレーションにスワップアウトすることはできません。
さらに、静的ファイナルにより、実行時にObjectMapperを再構成できなくなります。今はその理由を想像できないかもしれませんが、静的な最終パターンに自分をロックした場合、クラスローダーを分解するだけで再初期化できます。
ObjectMapperの場合は問題ありませんが、一般的には悪い習慣であり、シングルトンパターンまたは制御の反転を使用して長期間存続するオブジェクトを管理する以上の利点はありません。
これから学んだトリック PR 静的な最終変数として定義したくないが、オーバーヘッドを少し節約し、スレッドセーフを保証したい場合。
private static final ThreadLocal<ObjectMapper> om = new ThreadLocal<ObjectMapper>() {
@Override
protected ObjectMapper initialValue() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}
};
public static ObjectMapper getObjectMapper() {
return om.get();
}
著者の功績。