Est-il acceptable d'utiliser l'instance Gson comme champ statique dans un bean modèle (réutilisation)?

138

Voici le modèle que j'ai implémenté:

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);
    }
}

J'ai pensé qu'il était inutile de créer une nouvelle instance Gson pour chaque instance LoginSession.

Mais ce qui m'inquiète, ce sont les problèmes de sécurité des threads. Environ 1000 instances / s seront créées.

Est-il acceptable d'utiliser l'instance Gson comme champ statique?

Merci pour tous conseils / corrections.

philipjkim
la source

Réponses:

133

Cela me semble très bien. Il n'y a rien dans l'instance GSON qui la rend liée à une instance spécifique de LoginSession, elle doit donc être statique.

Les instances GSON devraient être thread-safe , et il y avait un bogue concernant ce qui a été corrigé.

MByD
la source
@slott, comment pouvez-vous regrouper / réutiliser les instances Gson? En instanciez-vous un à chaque fois que vous avez besoin de sérialiser? Ou utiliser un pool threadlocal?
Dilum Ranatunga
Nous utilisons GSON avec Google Volley et lorsque nous analysons les données JSON simultanément, nous voyons ce problème. D'après ce que je peux voir, cela est lié au fait que nous définissons un horodatage pour analyser les valeurs datetime.
slott
1
Datetime n'est pas thread-safe, cela peut en être la cause, non pas que GSON n'est pas thread-safe.
Andreas Mattisson
20

La Gsonclasse principale est thread-safe. Je viens de rencontrer un problème de sécurité des threads qui était censé être avec GSON. Le problème est survenu lors de l'utilisation d'une personnalisation JsonDeserializeret JsonSerializerpour l' Dateanalyse et la mise en forme. En fait, le problème de la sécurité des threads était lié à l'utilisation par ma méthode d'une SimpleDateFormatinstance statique qui n'est pas thread-safe. Une fois que j'ai enveloppé la statique SimpleDateFormatdans une ThreadLocalinstance, tout s'est bien passé.

entpnerd
la source
4
Une meilleure option peut être d'utiliser Apache commons FastDateFormat (partie de commons-lang), qui est explicitement threadsafe. commons.apache.org/proper/commons-lang/apidocs/org/apache/…
Marceau
Merci @Zaan. Bon conseil!
entpnerd
8

Selon les commentaires, le test unitaire existant ne teste pas vraiment beaucoup, soyez prudent avec tout ce qui concerne la sécurité des threads ...

Un test unitaire vérifie la sécurité des threads:

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

Vous vous demandez peut-être si ce test unitaire est suffisant pour trouver tous les problèmes possibles sur chaque configuration de machine possible? Des commentaires à ce sujet?

Il y a aussi cette phrase dans la documentation :

L'instance Gson ne conserve aucun état lors de l'appel d'opérations Json. Ainsi, vous êtes libre de réutiliser le même objet pour plusieurs opérations de sérialisation et de désérialisation Json.

Christophe Roussy
la source
3
J'aurais dit que ce test unitaire était terriblement insuffisant pour détecter les problèmes de concurrence. Tout d'abord, MyObject est une classe triviale sans collections complexes impliquées, donc la dé / sérialisation simultanée des listes et des cartes et d'autres objets complexes ne sont pas testées. Deuxièmement, la sérialisation n'est répétée que 10 fois pour chacun des 10 threads, ce qui est inadéquat. Troisièmement, les défauts de concurrence sont de toute façon notoirement difficiles à tester, car différentes configurations matérielles ont des caractéristiques d'exécution différentes, de sorte que tout test ne serait valide que s'il est garanti d'être exécuté sur toutes les configurations.
Lawrence Dol
1
Par exemple, ce test ne trouvera probablement aucune erreur de concurrence sur une machine à un seul cœur, car chaque thread se terminera probablement en une seule tranche de temps et les threads s'exécuteront donc consécutivement, pas simultanément.
Lawrence Dol
3
Non pour dire que ce n'est pas threadsafe, seulement que ce test ne garantit même pas à distance qu'il l'est.
Lawrence Dol
1

Nous avons eu des problèmes avec la sécurité des threads il y a quelque temps et nous l'avons résolu en utilisant FastDateFormat dans apache commons.

Je viens de créer un lien essentiel pour Gist autour de cela pour aider les personnes à se demander si les instances Gson peuvent être réutilisées. Ils n'ont pas de setters et tous les vars sont privés.

Donc, à part le problème SimpleDateFormat, je ne les vois pas maintenir leur état ailleurs.

Vérifiez - le. C'est la première fois que je réponds à l'un d'entre eux. Heureux de redonner pour une fois. :)

Aarengee
la source