2013-08-02 3 views
3

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

public class StreamThread extends Thread { 
    private Set<String> allSymbolSet = new HashSet<String>(Arrays.asList("USBC", "TCSD", "PCLJ")); 
    private PriorityBlockingQueue<String> priorityBlocking = new PriorityBlockingQueue<String>(); 

    public void addSymbols(String str) { 
     if (str != null) { 
      priorityBlocking.add(str); 
     } 
    } 

    public void run() { 
     while (true) { 
      try { 
       while (priorityBlocking.peek() != null) { 
        String symbol = priorityBlocking.poll(); 
        allSymbolSet.add(symbol); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

мой вопрос, я хочу, чтобы получить доступ к переменной allSymbolSet из другого класса

, что будет самый лучший подход, чтобы получить доступ к этой переменной с именем allSymbolSet из anoter класса, для этого у меня есть два варианта

  1. изменить спецификатор доступа allSymbolSet от частного до стандартного.

  2. Написать метод GET, который supoused вернуть Set

Пожалуйста, предложите мне, что будет хороший подход в этом случае ??

+1

Скорее всего 2, но * почему * другой класс пытается получить доступ к 'allSymbolSet', что он хочет с этим делать? – Joni

ответ

2

Несколько комментариев:

  • Если вы сделаете установить, не частный, какой-то код может изменить его (по ошибке или с целью), которые могут привести к противоречивому поведению в классе StreamThread. Не делай этого.
  • Предоставление простого геттера не решает проблему выше. Предпочитаете возвращать копию вашего набора.
  • Сделайте свои переменные окончательными, когда сможете, в многопотоковой среде - он решает многие проблемы безопасности потоков.
  • Предпочитает реализацию Runnable, чем простирающийся тему
  • Вам нужно будет синхронизировать все доступы к вашему набору (чтение и запись), например, с помощью synchronizedSet или даже лучше, обернув ConcurrentHashMap, который обычно обеспечивает более высокую производительность.
  • вместо peek + poll вы можете просто take из очереди

Так что ваш конечный класс может выглядеть следующим образом:

public class StreamTask implements Runnable { 

    private final Set<String> allSymbolSet; 
    private final PriorityBlockingQueue<String> priorityBlocking = new PriorityBlockingQueue<String>(); 

    public StreamTask() { 
     String[] symbols = {"USBC", "TCSD", "PCLJ"}; 
     //use a thread safe set, for example based on ConcurrentHashMap 
     allSymbolSet = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>()); 
     Collections.addAll(allSymbolSet, symbols); 
    } 

    public void addSymbols(String str) { 
     if (str != null) { 
      priorityBlocking.add(str); 
     } 
    } 

    public Set<String> getSymbols() { 
     return new HashSet<> (allSymbolSet); //return a copy 
    } 

    public void run() { 
     while (true) { 
      try { 
       allSymbolSet.add(priorityBlocking.take()); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

Наконец, я мог бы быть что-то отсутствует, но этот класс выглядит эквивалентно гораздо проще:

public class StreamTask { 

    private final Set<String> allSymbolSet; 

    public StreamTask() { 
     String[] symbols = {"USBC", "TCSD", "PCLJ"}; 
     //use a thread safe set, for example based on ConcurrentHashMap 
     allSymbolSet = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>()); 
     Collections.addAll(allSymbolSet, symbols); 
    } 

    public void addSymbols(String str) { 
     if (str != null) { 
      allSymbolSet.add(str); 
     } 
    } 

    public Set<String> getSymbols() { 
     return new HashSet<> (allSymbolSet); //return a copy 
    } 
} 
+0

+1 для создания копии при возврате Set. Хороший ответ –

+0

если я использую последнее ключевое слово, разрешит ли он изменять Set и PriorotyBlockingQueue? – Kiran

+1

@Kiran Вы можете добавлять или удалять из окончательного набора, но вы не можете переназначить его. Поэтому вы не можете написать: 'allSymbolSet = new HashSet <>()' после построения. – assylias

3

Лучший подход был бы метод получения и синхронизации доступа к объекту allSymbolSet, что-то вроде этого:

public Set<String> getAllSymbolSet() { 
    synchronized(allSymbolSet) { 
     return allSymbolSet; 
    } 
} 

, а также синхронизировать доступ к allSymbolSet внутри вашего потока.

+0

Почему это лучше ??? –

+0

Большое спасибо, но зачем мне синхронизировать это? Необходима ли синхронность в этом случае? – Kiran

+1

Да, потому что у вас будет два потока, связанных с одним и тем же HashSet, HashSet не является потокобезопасным – morgano

0

Лучший способ - это метод 2. Написание метода геттера. Если вы хотите разрешить устанавливать значения, используйте позднее сеттер. Затем ваши данные будут инкапсулированы.

0

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

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