从不同的类访问私有访问变量数据
Posted
技术标签:
【中文标题】从不同的类访问私有访问变量数据【英文标题】:Accessing private access variable data from different class 【发布时间】:2013-08-03 14:32:12 【问题描述】:我的项目中有这个线程,它不断运行并接受新符号
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
的变量的最佳方法是什么,为此我有两个选择
将 allSymbolSet 的访问说明符从私有修改为默认。
编写一个用于返回 Set 的 get 方法
请建议我,在这种情况下有什么好的方法??
【问题讨论】:
更有可能是2,但是为什么其他类尝试访问allSymbolSet
,它想用它做什么?
【参考方案1】:
最好的方法是 getter 方法并同步对对象 allSymbolSet
的访问,如下所示:
public Set<String> getAllSymbolSet()
synchronized(allSymbolSet)
return allSymbolSet;
并在你的线程中同步对allSymbolSet
的访问。
【讨论】:
非常感谢,但为什么我需要同步呢?在这种情况下是否需要同步?? 是的,因为你将有两个线程访问同一个 HashSet,HashSet 不是线程安全的 如果只想读取字段,真的需要同步吗? @AtishDipongkor 更好,因为在第一种情况下,您无法控制使用您的字段的内容,使用吸气剂您可以更好地控制如何共享您的对象。这种情况下需要同步访问 @NishantShreshth 是的,您需要同步才能阅读。或者考虑一个线程安全(er)实现***.com/questions/6992608/…【参考方案2】:几个cmets:
如果您将设置设为非私有,则某些代码可能会修改它(错误地或故意地),这可能会导致 StreamThread 类中的行为不一致。不要那样做。 提供简单的 getter 并不能解决上述问题。最好退回您的套装副本。 在多线程环境中尽可能将变量设为最终变量 - 它解决了许多线程安全问题。 宁愿实现 Runnable 而不是扩展 Thread 您将需要同步对您的集合的所有访问(读取和写入),例如使用synchronizedSet
,甚至更好地包装ConcurrentHashMap
,这通常会提供更好的性能。
您可以在队列中简单地使用take
而不是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 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
【讨论】:
+1 用于在返回 Set 时创建副本。很好的答案。 如果我使用 final 关键字,它会允许它修改 Set 和 PriorotyBlockingQueue 吗?? @Kiran 您可以添加到最终集或从中删除,但不能重新分配它。所以你不能写:allSymbolSet = new HashSet<>()
建后。
非常感谢,还有一个问题,我正在以这种方式创建 allSymbolSet,public Set更好的方法是方法 2。编写一个 getter 方法。如果您想允许设置值,请稍后使用设置器。然后你的数据将被封装。
【讨论】:
【参考方案4】:编写一个应该返回 Set 的 get 方法。通过使用它,您的 private 仍然是私有的,并且您还可以使用同一类的 Object 从外部访问它。
【讨论】:
以上是关于从不同的类访问私有访问变量数据的主要内容,如果未能解决你的问题,请参考以下文章