Java 从不同类访问私有访问变量数据

Java 从不同类访问私有访问变量数据,java,Java,我的项目中有一个线程,它不断地接受新的符号 public class StreamThread extends Thread { private Set<String> allSymbolSet = new HashSet<String>(Arrays.asList("USBC", "TCSD", "PCLJ")); private PriorityBlockingQueue<String> priorityBlocking = new Pri

我的项目中有一个线程,它不断地接受新的符号

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();
            }
        }
    }
}
公共类StreamThread扩展线程{
私有集allSymbolSet=newhashset(Arrays.asList(“USBC”、“TCSD”、“PCLJ”);
private PriorityBlockingQueue priorityBlocking=new PriorityBlockingQueue();
公共void addSymbols(字符串str){
如果(str!=null){
优先阻塞。添加(str);
}
}
公开募捐{
while(true){
试一试{
while(priorityBlocking.peek()!=null){
String symbol=priorityBlocking.poll();
所有符号集。添加(符号);
}
}捕获(例外e){
e、 printStackTrace();
}
}
}
}
我的问题是,我想从另一个类访问变量allSymbolSet

从另一个类访问名为
allSymbolSet
的变量的最佳方法是什么,为此我有两个选择

  • 将allSymbolSet的访问说明符从private修改为default。


  • 编写一个get方法,用于返回集合


  • 请告诉我,在这种情况下,最好的方法是什么???

    最好的方法是getter方法并同步对对象的访问
    allSymbolSet
    ,如下所示:

    public Set<String> getAllSymbolSet() {
        synchronized(allSymbolSet) {
            return allSymbolSet;
        }
    }
    
    public Set getAllSymbolSet(){
    已同步(所有符号集){
    返回所有符号集;
    }
    }
    

    还可以在线程内同步对
    所有符号集的访问。

    更好的方法是方法2。编写一个getter方法。如果要允许设置值,请稍后使用setter。然后,您的数据将被封装。

    编写一个get方法,该方法应返回集合。使用此方法,您的私有文件将保持私有,并且您还可以使用同一类的对象从外部访问它。

    一些注释:

    • 如果将该集设置为非私有,某些代码可能会(错误地或故意地)修改它,从而导致StreamThread类中的行为不一致。不要那样做
    • 提供一个简单的getter并不能解决上述问题。更喜欢返回您的设置副本
    • 在多线程环境中,尽可能将变量设置为最终变量-这解决了许多线程安全问题
    • 更喜欢实现可运行而不是扩展线程
    • 您需要同步对集合的所有访问(读和写),例如使用
      synchronizedSet
      ,或者更好地包装
      ConcurrentHashMap
      ,这通常会提供更好的性能
    • 您只需从队列中取出
    ,而不是
    peek
    +
    poll
    所以你的最后一节课看起来像:

    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类StreamTask实现可运行{
    私人最终设置所有符号集;
    private final PriorityBlockingQueue priorityBlocking=new PriorityBlockingQueue();
    公共流任务(){
    字符串[]符号={“USBC”、“TCSD”、“PCLJ”};
    //使用线程安全集,例如基于ConcurrentHashMap
    allSymbolSet=Collections.newSetFromMap(新的ConcurrentHashMap());
    Collections.addAll(allSymbolSet,symbols);
    }
    公共void addSymbols(字符串str){
    如果(str!=null){
    优先阻塞。添加(str);
    }
    }
    公共集合getSymbols(){
    返回新的HashSet(allSymbolSet);//返回一个副本
    }
    公开募捐{
    while(true){
    试一试{
    allSymbolSet.add(priorityBlocking.take());
    }捕获(例外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
        }
    }
    
    公共类StreamTask{
    私人最终设置所有符号集;
    公共流任务(){
    字符串[]符号={“USBC”、“TCSD”、“PCLJ”};
    //使用线程安全集,例如基于ConcurrentHashMap
    allSymbolSet=Collections.newSetFromMap(新的ConcurrentHashMap());
    Collections.addAll(allSymbolSet,symbols);
    }
    公共void addSymbols(字符串str){
    如果(str!=null){
    所有符号集添加(str);
    }
    }
    公共集合getSymbols(){
    返回新的HashSet(allSymbolSet);//返回一个副本
    }
    }
    
    更可能是2,但是为什么另一个类尝试访问
    allSymbolSet
    ,它想用它做什么?非常感谢,但是为什么我需要同步呢??在这种情况下是否需要同步?是的,因为您将有两个线程访问同一个哈希集,哈希集不是线程安全的。如果您只想读取字段,是否确实需要同步?@AtishDipongkor更好,因为在第一种情况下,您无法控制使用字段的内容,使用getter,您可以更好地控制如何共享对象。在这种情况下,有必要同步access@NishantShreshth是的,你需要同步来阅读。或者考虑线程安全(ER)实现+ 1,也用于在返回集合时创建副本。回答很好。如果我使用final关键字,它是否允许它修改集合和PriorotyBlockingQueue???@Kiran您可以添加到最终集合或从最终集合中删除,但您不能重新分配它。因此,在构建之后,您无法编写:
    allSymbolSet=new HashSet()
    。非常感谢,请再问一个问题,我正在以这种方式创建allSymbolSet,public Set allSymbolSet=Collections.synchronizedSet(新的HashSet,我还需要同步getter方法吗???@Kiran如果你像我建议的那样返回一个副本,那么是的,你需要同步,因为副本创建涉及需要手动同步的迭代。这就是我建议在ConcurrentHashMap中使用包装器的原因之一