Можно ли использовать экземпляр Gson в качестве статического поля в компоненте модели (повторное использование)?

143

Вот модель, которую я реализовал:

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

Я думал, что создавать новый экземпляр Gson для каждого экземпляра LoginSession бесполезно.

Но меня беспокоят проблемы с поточной безопасностью. Будет создано около 1000+ экземпляров в секунду.

Можно ли использовать экземпляр Gson в качестве статического поля?

Спасибо за любые советы / исправления.

филиппьким
источник

Ответы:

136

Мне кажется, это нормально. В экземпляре GSON нет ничего, что связывало бы его с конкретным экземпляром LoginSession, поэтому он должен быть статическим.

Экземпляры GSON должны быть потокобезопасными , и в этом была исправлена ​​ошибка .

МБыД
источник
@slott, как вы, ребята, объединяете / повторно используете экземпляры Gson? Вы создаете один экземпляр каждый раз, когда вам нужно сериализовать? Или использовать пул threadlocal?
Дилум Ранатунга
Мы используем GSON вместе с Google Volley, и при параллельном анализе данных JSON мы видим эту проблему. Насколько я понимаю, это связано с тем, что мы определяем метку времени для анализа значений даты и времени.
slott
1
Datetime не является потокобезопасным, это может быть причиной, а не потому, что GSON не является потокобезопасным.
Андреас Мэттиссон
21

Базовый Gsonкласс является потокобезопасным. Я только что столкнулся с проблемой безопасности потоков, которая предположительно была связана с GSON. Проблема возникла при использовании кастома JsonDeserializerи JsonSerializerдля Dateсинтаксического анализа и форматирования. Как оказалось, проблема с поточной безопасностью заключалась в том, что мой метод использовал статический SimpleDateFormatэкземпляр, который не является поточно-ориентированным. Как только я обернул статику SimpleDateFormatв ThreadLocalэкземпляр, все сработало нормально.

Entpnerd
источник
4
Лучшим вариантом может быть использование Apache commons FastDateFormat (часть commons-lang), который явно является потокобезопасным. commons.apache.org/proper/commons-lang/apidocs/org/apache/…
Марсо,
Спасибо @Zaan. Отличный совет!
entpnerd 03
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 потоков, что неадекватно. В-третьих, как известно, сбои параллелизма в любом случае сложно тестировать, потому что разные конфигурации оборудования имеют разные характеристики времени выполнения, поэтому любой тест будет действительным только в том случае, если он гарантированно запускается во всех конфигурациях.
Лоуренс Дол
1
Например, этот тест, скорее всего, не обнаружит каких-либо ошибок параллелизма на одноядерной машине, поскольку каждый поток, вероятно, будет завершен в пределах одного временного интервала, и поэтому потоки будут выполняться последовательно, а не одновременно.
Лоуренс Дол
3
Нет, чтобы сказать, что это не потокобезопасно, только то, что этот тест даже отдаленно не гарантирует, что это так.
Лоуренс Дол
1

Некоторое время назад у нас были проблемы с безопасностью потоков, и мы решили их, используя FastDateFormat в общих ресурсах apache.

Просто создал ссылку на Gist вокруг этого, чтобы помочь людям, которые задаются вопросом, можно ли повторно использовать экземпляры Gson. У них нет сеттеров, и все вары частные.

Поэтому, кроме проблемы SimpleDateFormat, я не вижу, чтобы они поддерживали состояние где-либо еще.

Проверьте это . Я впервые отвечаю на один из них. Рад вернуть хоть раз. :)

aarengee
источник