同步一组线程



我正在用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获取自己的锁。

所有线程都必须小心,尽可能限制它们持有锁的范围,因此,文件读取线程应在修改映射之前立即获取写锁,保持它直到一个条目的所有修改完成,然后释放它。 其他线程不会相互阻塞,因此它们原则上可以保持更长时间的锁,但这样做会阻止文件读取器。

最新更新