【发布时间】:2016-02-02 20:55:04
【问题描述】:
我尝试使用多线程来访问 Hashtable,因为 Hashtable 在获取时是线程安全的。但我无法让它工作。
我认为本地计数器的总和应该等于 Hashtable 或 global_counter 的大小。但事实并非如此。
多个线程得到 java.util.NoSuchElementException: Hashtable Enumerator 错误。我认为错误是由于 Hashtable 的枚举造成的。是这样吗?
TestMain:
public class TestMain {
// MAIN
public static void main(String argv[]) throws InterruptedException
{
Hashtable<Integer, Integer> id2 = new Hashtable<Integer, Integer>();
for (int i = 0; i < 100000; ++i)
id2.put(i, i+1);
int num_threads = Runtime.getRuntime().availableProcessors() - 1;
ExecutorService ExeSvc = Executors.newFixedThreadPool(num_threads);
for (int i = 0; i < num_threads; ++i)
{
ExeSvc.execute(new CalcLink(id2, i));
}
ExeSvc.shutdown();
ExeSvc.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
计算链接:
public class CalcLink implements Runnable {
private Hashtable<Integer, Integer> linktable;
private static Enumeration keys;
private static int global_counter;
private int thread_id;
private int total_size;
public CalcLink(Hashtable<Integer, Integer> lt, int id)
{
linktable = lt;
keys = lt.keys();
thread_id = id;
total_size = lt.size();
global_counter = 0;
}
private synchronized void increment()
{
++global_counter;
}
@Override
public void run()
{
int counter = 0;
while (keys.hasMoreElements())
{
++counter;
increment();
Integer key = (Integer)keys.nextElement();
Integer value = linktable.get(key);
}
System.out.println("local counter = " + Integer.toString(counter));
if (thread_id == 1)
System.out.println("global counter = " + Integer.toString(global_counter));
}
}
【问题讨论】:
-
每个单独的操作可能是线程安全的,但这并不意味着在没有明确持有锁的情况下一个接一个地执行它们是线程安全的。 (此外,
Hashtable和Enumeration目前已被弃用至少 15 年。) -
不幸的是并发编程不是可以通过反复试验有效地学习的东西(正如我自己发现的那样),我肯定会找到一本提供完整概述的好书或教程什么是什么,例如 Java Concurrency in Practice,甚至是官方 Java 教程。
-
使用多线程从 Hashtable 或 HashMap 读取元素的最佳/更好的方法是什么?
-
@biziclop,感谢您的建议
标签: java multithreading hashtable