I am trying to implement a frequency counter that counts the occurrences of each element. In this case two processes can call the hfc.count(1) and hfc.count(2) concurrently. I'm summing up the the number of processes to make sure its 2000000, but I am off by like ~100000.
class FrequencyCounter {
HashMap<Integer, Integer> frequencyMap = new HashMap<Integer, Integer>();
int max ;
FrequencyCounter(int max) {
this.max = max ;
for (int i = 0; i < max; i++) {
frequencyMap.put(i, 0);
}
}
void count(int event) {
synchronized (this) {
if (frequencyMap.containsKey(event)) {
frequencyMap.put(event, frequencyMap.get(event) + 1);
}
}
}
/**
* @param event
* @return the frequency of event since creation.
*/
int frequency(int event) {
return frequencyMap.get(event);
}
Concurrent freq counter
class HighFrequencyCounter extends FrequencyCounter {
int[] count;
static int n;
/**
* @ClassInvariant {frequencyMap != null && max > 0}
*/
HighFrequencyCounter(int max) {
super(max);
count = new int[max];
}
void count(int event) {
if (count[event] != 0) {
n++;
super.count(event);
}
if (count[event] < 1) {
count[event] = 1;
frequencyMap.put(event, frequencyMap.get(event) + 1);
count[event] = 0;
}
}
public static void main(String Args[]) throws InterruptedException {
class HEventer extends Thread {
HighFrequencyCounter hfc;
HEventer(HighFrequencyCounter hfc) {
this.hfc = hfc;
}
public void run() {
Random r = new Random();
for (int i = 0; i < 20000; i++) {
hfc.count(r.nextInt(10));
}
}
}
HighFrequencyCounter hfc = new HighFrequencyCounter(10);
HEventer hev[] = new HEventer[1000];
for (int i = 0; i < 1000; i++) {
hev[i] = new HEventer(hfc);
}
long hstartTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
hev[i].start();
}
for (int i = 0; i < 1000; i++) {
hev[i].join();
}
long hendTime = System.currentTimeMillis();
System.out.println(hendTime - hstartTime);
int sumProcesses = 0;
for (int i = 0; i < 10; i++) {
System.out.println(i + " = " + hfc.frequency(i));
sumProcesses = sumProcesses + hfc.frequency(i);
}
System.out.println(sumProcesses);
System.out.println(hfc.n);
}
}
I know this is possible using java's concurrent hashmaps, but i am trying to synchronize just simple hashmaps. My normal frequencyCounter class does, work as expect, but I'm not sure how i to synchronize the count method.
For high frequency counter i synchronized the count method, and used wait within the while(count[event] != 0) wait() however this was allowing for concurrent calls because i needed to synchronize the count method.