我试图使用多线程来访问Hashtable,因为Hashtable是线程安全的get。但我无法得到它的工作。java多线程访问Hashtable
我认为本地计数器的总和应该等于Hashtable或global_counter的大小。但事实并非如此。
多个线程获取java.util.NoSuchElementException:Hashtable枚举器错误。我认为这个错误是由于枚举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);
}
}
CalcLink:
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并发实践,甚至是官方Java教程。 – biziclop
什么是使用多线程读取Hashtable或HashMap中元素的最佳/更好的方法? – stevenhz