GsonインスタンスをモデルBeanの静的フィールドとして使用しても問題ありませんか(再利用)。


138

これが私が実装したモデルです:

public class LoginSession {
    private static final Gson gson = new Gson();

    private String id;
    private String name;
    private long timestamp;

    public LoginSession(String id, String name) {
        this.id = id;
        this.name = name;
        this.timestamp = System.currentTimeMillis();
    }

    public String toJson() {
        return gson.toJson(this);
    }

    public static LoginSession fromJson(String json) {
        checkArgument(!isNullOrEmpty(json));
        return gson.fromJson(json, LoginSession.class);
    }
}

すべてのLoginSessionインスタンスに対して新しいGsonインスタンスを作成することは役に立たないと思いました。

しかし、私が心配しているのは、スレッドの安全性の問題です。約1000以上のインスタンス/秒が作成されます。

Gsonインスタンスを静的フィールドとして使用しても問題ありませんか?

アドバイス/修正をありがとう。

回答:


133

私には問題ないようです。GSONインスタンスには、の特定のインスタンスに関連するLoginSessionものはないため、静的である必要があります。

GSONインスタンスはスレッドセーフである必要があり、それに関するバグが修正されました。


@スロット、どうやってGsonインスタンスをプール/再利用しますか?シリアル化する必要があるたびにインスタンス化しますか?または、スレッドローカルプールを使用しますか?
Dilum Ranatunga 2013

GSONをGoogle Volleyと一緒に使用し、JSONデータを同時に解析すると、この問題が発生します。私が見ることができることから、これは日時値を解析するためのタイムスタンプを定義するという事実に関連しています。
スロット2013年

1
日時がスレッドセーフではない、それが原因である可能性があります。GSONがスレッドセーフではないということではありません。
Andreas Mattisson 2016年

20

コアGsonクラスはスレッドセーフです。GSONで発生したと思われるスレッドセーフの問題が発生しました。この問題は、カスタムJsonDeserializerを使用しJsonSerializerDate解析およびフォーマットするときに発生しました。結局のところ、スレッドセーフの問題は、私のメソッドSimpleDateFormatがスレッドセーフではない静的インスタンスを使用することでした。静的SimpleDateFormatThreadLocalインスタンスでラップすると、すべてがうまくいきました。


4
より良いオプションは、明示的にスレッドセーフであるApache commons FastDateFormat(commons-langの一部)を使用することです。commons.apache.org/proper/commons-lang/apidocs/org/apache/...
マルソー

@ザーンありがとう。すばらしいヒントです。
entpnerd 2016年

8

コメントによると、既存の単体テストは実際にはあまりテストしていません。スレッドセーフティに関連するものには注意してください...

スレッドの安全性をチェックする単体テストがあります。

/**
 * Tests for ensuring Gson thread-safety.
 *
 * @author Inderjeet Singh
 * @author Joel Leitch
 */
public class ConcurrencyTest extends TestCase {
  private Gson gson;
  ...

この単体テストは、考えられるすべてのマシン構成で考えられるすべての問題を見つけるのに十分かどうか疑問に思われるかもしれません。これについてのコメント?

ドキュメントにもこの文があります:

Gsonインスタンスは、Json操作を呼び出している間、状態を維持しません。そのため、複数のJsonシリアル化および逆シリアル化操作で同じオブジェクトを自由に再利用できます。


3
このユニットテストは、同時実行の問題を検出するにはひどく不十分だったと思います。まず、MyObjectは複雑なコレクションを含まない自明なクラスであるため、リストとマップ、およびその他の複雑なオブジェクトの同時非直列化はテストされません。次に、シリアル化は10スレッドごとに10回しか繰り返されないため、不十分です。第3に、ハードウェア構成が異なるとランタイム特性も異なるため、並行性の障害をテストすることは非常に困難です。そのため、すべての構成で実行が保証されている場合にのみ、テストは有効です。
Lawrence Dol 2014

1
たとえば、各スレッドはおそらく単一のタイムスライス内で完了し、スレッドは同時にではなく連続して実行されるため、このテストでは、単一コアマシンで同時実行障害は検出されない可能性があります。
ローレンスドル

3
スレッドセーフではないことは言うまでもありません。このテストでは、それがリモートであることが保証されることさえありません。
ローレンスドル

1

しばらく前にスレッドセーフティの問題があり、ApacheコモンズでFastDateFormatを使用して解決しました。

Gsonインスタンスを再利用できるかどうか疑問に思う人々を助けるために、この周りにGistの gist リンクを作成したところです。セッターはなく、すべての変数はプライベートです。

したがって、SimpleDateFormatの問題以外は、他の場所で状態を維持することはありません。

ぜひチェックてみてください。これはこれらの1つに返信するのは初めてです。一度だけお返しさせていただきます。:)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.