我正在编写代码让4个线程构建直方图。
我在main中有一个数组:
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);
}
所以基本上我想做的就是遍历这个数组并计算每个数字出现的次数。
所以我编写了我的线程类,并且使用了AtomicInteger
,我认为这有助于解决多个线程试图同时访问同一个索引的问题。
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;
}
然而,这并没有解决我的问题。有些线程同时访问数组,使count
数组的值大于array
数组的长度。
我认为问题在于检查的布尔数组。我有一种感觉,多个线程同时访问相同的布尔数组索引。
我认为这可能是一个简单的修复,但我只是没有看到它。
有什么建议吗?
我尝试了AtomicBoolean
数组,但它没有帮助。下面是同一个类,但实现了AtomicBoolean
数组。
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();
}
答案 0 :(得分:2)
您需要使用compareAndSet
将if
声明置于互斥:
if (this.check[i].compareAndSet(false, true))
{
int number = array[i];
count[number].incrementAndGet();
}
这两者都会检查并以原子方式设置值。
如果没有compareAndSet
,两个线程可能会检查该值并同时输入if
块,然后才有机会调用set(true)
。