我正在用Java编写一个程序,我有一个HashMap<String, Deque<Integer>> info;
我的数据是一小时时间段内访问的维基百科页面列表,以及每个页面的访问次数。
de Florian_David_Fitz 18
de G%C3%BCnther_Jauch 1
de Gangs_of_New_York 2
de Georg_VI._(Vereinigtes_K%C3%B6nigreich) 7
de Gerry_Rafferty 2
这些数据从上面存储在HashMap
中,页面名称作为键,Deque
每小时更新一次,该小时的访问次数。
我想有一个线程ThreadRead
读取输入文件并将信息存储在HashMap
中。然后HashMap
中的每个键都有一个ThreadCompute
线程,该线程使用关联的Deque
。
ThreadRead
需要在活动时锁定所有ThreadComputes
,然后在完成后唤醒它们,以便ThreadComputes
可以同时工作。
如果我需要为每个ThreadCompute
使用不同的互斥锁,那么如何在ThreadRead
工作时锁定所有互斥锁?我怎样才能从ThreadRead
完成时唤醒所有ThreadComputes
?
我用info
作为ThreadRead
的锁,每个ThreadCompute
info.get(key)
但它没有按我的预期工作。
编辑:
我添加了一些代码来尝试更清楚地说明问题。这是我目前所拥有的:
HashMap<String, Deque<Integer>> info;
boolean controlCompute, control Read;
private static class ThreadRead extends Thread {
public void run() {
while(controlRead) {
try {
read();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void read() throws InterruptedException{
synchronized(info){
while(count==numThreads){
for (File file: files){
reader.parse(file, info); // Reads the file and store the data in the Hashmap
keys=true;
while(info.getSizeDeque()>10){
count=0;
info.wait();
info.notifyAll();
}
}
}
controlRead=false;
}
}
}
private static class ThreadCompute extends Thread {
public String key;
public void run() {
while(controlCompute) {
try {
compute();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void compute() throws InterruptedException{
synchronized(info.get(key)){
if(count!=numThreads){
algorithms(); //Here I apply the algorithms to the integers in the deque
if(controlRead){
info.get(key).removeFirst();
count++;
if(count==numThreads){
info.notify();
info.get(key).wait();
}
info.get(key).wait();
}
if(info.isEmptyDeque(key)){
controlCompute=false;
}
}
}
}
}
java.util.concurrent.locks.ReentrantReadWriteLock
对这类问题很好。 应该只有一个实例来保护整个HashMap
。 文件读取器需要获取ReadWriteLock
的写锁定,因为它想要修改映射。 其他线程需要各自从一个ReadWriteLock
获取自己的读锁。
所有线程都必须小心,尽可能限制它们持有锁的范围,因此,文件读取线程应在修改映射之前立即获取写锁,保持它直到一个条目的所有修改完成,然后释放它。 其他线程不会相互阻塞,因此它们原则上可以保持更长时间的锁,但这样做会阻止文件读取器。