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
的变量的最佳方法是什么,为此我有两个选择
请告诉我,在这种情况下,最好的方法是什么???最好的方法是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中使用包装器的原因之一