2016-04-14 10 views
0

Ich schreibe Code, um 4 Threads ein Histogramm erstellen zu lassen.Verwenden von Threads auf einem Atomic Integer Array

Ich habe ein Array in Haupt:

int N = 10000; 
Random r = new Random(); 
int[] a = new int[N]; 

for (int i = 0; i < a.length; i++) 
{ 
    a[i] = Math.abs(r.nextInt() % 100); 
} 

Also im Grunde, was ich tun möchte, ist Zyklus durch diese Anordnung und zählt, wie oft jede Zahl.

Also habe ich meine Thread-Klasse geschrieben, und ich habe AtomicInteger verwendet, die ich dachte, würde helfen, das Problem von mehreren Threads zu lösen, die versuchen, auf den gleichen Index gleichzeitig zuzugreifen.

import java.util.concurrent.atomic.AtomicInteger; 

public class UseThread implements Runnable 
{ 
private static int[] array; 
private static AtomicInteger[] count; 
private static boolean[] check; 

public UseThread(int[] array, AtomicInteger[] count) 
{ 
    this.array = array; 
    this.count = count; 
    this.check = new boolean[array.length]; 
} 

public void run() 
{ 
    for (int i = 0; i < array.length; i++) 
    { 
     if (!getIndex(this.check[i])) 
     { 
      this.check[i] = true; 
      int number = array[i]; 
      count[number].incrementAndGet(); 
     } 
    } 
} 

public synchronized static boolean getIndex(boolean check2) 
{ 
    return check2; 
} 

Allerdings hat dies mein Problem nicht ganz behoben. Einige der Threads greifen gleichzeitig auf das Array zu, wodurch das Array count einen größeren Wert als die Länge des Arrays array aufweist.

Ich denke, das Problem liegt in der booleschen Überprüfung. Ich habe das Gefühl, dass mehrere Threads gleichzeitig auf denselben booleschen Array-Index zugreifen.

Ich denke, es ist wahrscheinlich eine einfache Lösung, aber ich sehe es einfach nicht.

Irgendwelche Vorschläge ??

Ich habe versucht, die AtomicBoolean Array, aber es hat nicht geholfen. Unten ist die gleiche Klasse, aber mit dem AtomicBoolean Array implementiert.

import java.util.concurrent.atomic.AtomicBoolean; 
import java.util.concurrent.atomic.AtomicInteger; 

public class Assign7Q3 implements Runnable 
{ 
private static int[] array; 
private static AtomicInteger[] count; 
private static AtomicBoolean[] check; 

public Assign7Q3(int[] array, AtomicInteger[] count) 
{ 
    this.array = array; 
    this.count = count; 
    this.check = new AtomicBoolean[array.length]; 
    for(int i = 0; i < check.length; i ++) 
     check[i] = new AtomicBoolean(false); 
} 

public void run() 
{ 
    for (int i = 0; i < array.length; i++) 
    { 
     //System.out.println(this.check[i].get()); 
     if (!getIndex(this.check[i])) 
     { 
      this.check[i].set(true); 
      int number = array[i]; 
      count[number].incrementAndGet(); 
     } 
    } 
} 

public synchronized static boolean getIndex(AtomicBoolean check2) 
{ 
    return check2.get(); 
} 
+1

Würde es Ihnen etwas ausmachen, * das Problem * zu erklären? –

+0

Ich denke, das Problem ist in der 'boolean' Check-Array der Überprüfung. Ich habe das Gefühl, dass mehrere Threads gleichzeitig auf denselben booleschen Check-Array-Index zugreifen. @YassinHajaj –

+0

Korrigieren. Schalte es auf 'AtomicBoolean', ja? –

Antwort

2

Sie benötigen compareAndSet für Ihre if Anweisung verwenden mutally exklusiv zu sein:

if (this.check[i].compareAndSet(false, true)) 
{ 
    int number = array[i]; 
    count[number].incrementAndGet(); 
} 

beide Prüfungen Diese und setzt atomar den Wert.

Ohne compareAndSet besteht die Möglichkeit, dass zwei Threads den Wert prüfen und gleichzeitig den if Block eingeben können, bevor eine set(true) anrufen kann.

+0

Vielen Dank, das habe ich nicht bemerkt. Sehr geschätzt –