【发布时间】:2009-12-03 19:55:19
【问题描述】:
所以我正在参加 Java 速度竞赛。我有(处理器数量)线程在工作,它们都需要添加到二叉树中。最初我只是使用了一个同步的 add 方法,但我想这样做,以便线程可以通过树相互跟随(每个线程只有它正在访问的对象上的锁)。不幸的是,即使对于一个非常大的文件(48,000 行),我的新二叉树也比旧二叉树慢。我认为这是因为我每次在树中移动时都会获取和释放锁。这是最好的方法还是有更好的方法?
每个节点都有一个名为lock的ReentrantLock,getLock()和releaseLock()只需调用lock.lock()和lock.unlock();
我的代码:
public void add(String sortedWord, String word) {
synchronized(this){
if (head == null) {
head = new TreeNode(sortedWord, word);
return;
}
head.getLock();
}
TreeNode current = head, previous = null;
while (current != null) {
// If this is an anagram of another word in the list..
if (current.getSortedWord().equals(sortedWord)) {
current.add(word);
current.releaseLock();
return;
}
// New word is less than current word
else if (current.compareTo(sortedWord) > 0) {
previous = current;
current = current.getLeft();
if(current != null){
current.getLock();
previous.releaseLock();
}
}
// New word greater than current word
else {
previous = current;
current = current.getRight();
if(current != null){
current.getLock();
previous.releaseLock();
}
}
}
if (previous.compareTo(sortedWord) > 0) {
previous.setLeft(sortedWord, word);
}
else {
previous.setRight(sortedWord, word);
}
previous.releaseLock();
}
编辑:澄清一下,我的代码结构如下:主线程从文件中读取输入并将单词添加到队列中,每个工作线程从队列中提取单词并执行一些工作(包括对它们进行排序和添加他们到二叉树)。
【问题讨论】:
-
一个小建议:您可能想要减去一个而不是 NumberOfProcessors 线程 - 因为操作系统至少会使用一个,为每个处理器定义一个线程几乎可以保证一些上下文交换开销。
-
我认为这会很好,因为假设线程会相互等待很多时间并不是不合理的。
-
如果他们互相等待,那就不好了,因为他们没有工作。
-
这就是重点。他们在添加到此列表时互相等待。即使使用花哨的锁定,他们仍然将大部分时间花在彼此等待上。
-
问题和大多数答案中有一些非常错误的术语:B 树不是二叉树,它是一个复杂得多的数据结构:en.wikipedia.org/wiki/B-tree
标签: java multithreading optimization binary-tree