2016-01-24 3 views
0

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

Я придумал код, как показано ниже.

public class Example { 

    private Example() {} 

    private static volatile Reference<List<Integer>> ref = new WeakReference<>(null); 

    public static List<Integer> get() { 
     List<Integer> list; 
     if ((list = ref.get()) != null) 
      return list; 
     synchronized (Example.class) { 
      if ((list = ref.get()) != null) 
       return list; 
      list = compute(); 
      ref = new WeakReference<>(list); 
      return list; 
     } 
    } 

    private static List<Integer> compute() { 
     // Some expensive computation producing a List with millions of elements 
    } 
} 

Тогда вы можете сделать этот список поле экземпляра, выполнив

public class MyClass { 

    private final List<Integer> list = Example.get(); 
} 

Этот код, кажется, работает, но я не уверен, если я использую volatile, synchronized, WeakReference и двойной проверки идиомы правильно. Может ли кто-нибудь увидеть какие-либо проблемы с этим кодом или предложить альтернативный/лучший способ достичь этого?

ответ

0

Выглядит хорошо, но я думаю, что volatile не требуется. По крайней мере, если вы только назначаете его изнутри блока synchronized, блок synchronization должен предотвращать memory consistency errors

Смежные вопросы