2012-04-30 1 views
103

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

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 как статическое поле?

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

ответ

90

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

экземпляры GSON should be thread-safe, а также был установлен bug regarding.

+7

У нас просто был сбой из-за проблем с параллелизмом с GSON. Поэтому я не думаю, что это 100% -ная потоковая безопасность - по крайней мере, не звоните в Json. – slott

+0

@slott, как вы, ребята, собираете/повторно используете экземпляры Gson? Вы создаете экземпляр каждый раз, когда вам нужно сериализовать? Или использовать threadlocal пул? –

+0

Мы используем GSON вместе с Google Volley, и когда мы анализируем данные JSON параллельно, мы видим эту проблему. Из того, что я вижу, это связано с тем, что мы определяем временную метку для синтаксического анализа значений даты и времени. – slott

8

Согласно комментариям существующий тестовый модуль не действительно испытывают много, будьте осторожны с, что связано с резьбой безопасности ...

Существует unit test проверки безопасности потока:

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

Вы может задаться вопросом, достаточно ли этого модульного теста, чтобы найти все возможные проблемы при каждой возможной конфигурации машины? Любые комментарии по этому поводу?

Существует также это предложение в docs:

Экземпляр Gson не запоминают состояние при вызове JSon операций. Таким образом, вы можете повторно использовать один и тот же объект для нескольких операций по сериализации и десериализации Json.

+2

Я бы сказал, что этот юнит-тест был крайне неадекватен для обнаружения проблем параллелизма. Во-первых, MyObject - это тривиальный класс, в котором нет сложных коллекций, поэтому параллельная де-сериализация списков и карт и других сложных объектов не тестируется. Во-вторых, сериализация выполняется только по 10 раз за каждый из 10 потоков, что является недостаточным.В-третьих, ошибки параллелизма, как правило, трудно проверить в любом случае, потому что разные конфигурации оборудования имеют разные характеристики времени выполнения, поэтому любой тест будет действителен только в том случае, если он будет работать во всех конфигурациях. –

+0

Например, этот тест, скорее всего, не обнаружит ошибки параллелизма на одноядерной машине, поскольку каждый поток, вероятно, завершится в течение одного таймлиса, и потоки будут запускаться последовательно, а не одновременно. –

+1

Нет, чтобы сказать, что это не потокобезопасно, только то, что этот тест не дает даже отдаленной гарантии, что это так. –

10

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

+2

Лучшим вариантом может быть использование общих ресурсов Apache FastDateFormat (часть commons-lang), которая явно небезопасна. https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/time/FastDateFormat.html – Zaan

+0

Спасибо @Zaan. Отличный совет! – entpnerd