3

I have this Thread inside my Project which runs continously accepting new symbols

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();
            }
        }
    }
}

my question is , i want to access the variable allSymbolSet from another class

what will be the best approach to get access to this variable named allSymbolSet from anoter class , for this i have two choices

  1. modify the access specifier of allSymbolSet from private to default .

  2. Write a get Method which is supoused to return the Set

Please suggest me , what will be the good approach in this case ??

4

4 回答 4

2

Best approach would be the getter method AND synchronize the access to the object allSymbolSet, something like this:

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

and also synchronize the access to allSymbolSet inside your thread.

于 2013-08-02T10:40:22.917 回答
1

几点评论:

  • 如果您将设置设为非私有,则某些代码可能会修改它(错误或故意),这可能会导致 StreamThread 类中的行为不一致。不要那样做。
  • 提供一个简单的 getter 并不能解决上述问题。更喜欢返回您的套装的副本。
  • 在多线程环境中尽可能使您的变量最终化 - 它解决了许多线程安全问题。
  • 更喜欢实现 Runnable 而不是扩展 Thread
  • 您将需要同步对您的集合的所有访问(读取和写入),例如通过使用 asynchronizedSet甚至更好地包装 aConcurrentHashMap通常提供更好的性能。
  • 而不是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
    }
}
于 2013-08-02T10:48:42.757 回答
0

Better way is method 2. Writing a getter method. If you want to allow set the values then use a setter later. Then your data will be encapsulated .

于 2013-08-02T10:40:27.903 回答
0

Write a get Method which is supposed to return the Set. by using this your private remains private and you also access it from outside using Object of the same class.

于 2013-08-02T10:40:58.807 回答