使用多线程处理对Java数组进行分区和分析 [英] Partitioning and analyzing a java array with multithreaded processing

查看:136
本文介绍了使用多线程处理对Java数组进行分区和分析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须通过for循环初始化一个浮点[12000] 12000次。然后我扫描数组以查找超过特定阈值的值。如果值超过阈值,我操纵某个对象的实例变量。

I have to initialize a float[12000] via a for loop 12000 times. I then scan the array to look for values exceeding a certain threshold value. If the value exceeds the threshold, I manipulate an instance variable of a certain object.

示例:

Random random = new Random();
float[] x = new float[12000];

for (int i = 0; i < x.length; i++) {
  x[i] = random.nextFloat();
}

for (int i = 0; i < x.length; i++) {
  if (x[i] >= 0.75) {
  \\ do something interesting
  }
}

基本上,我有更改数组的值,并在每次长度为12000的新数组上执行12000次。有趣的代码只是在另一个数据结构中查找该索引并调用setter。根据我的系统时间计算,我需要大约13个小时。我的机器上有8个处理器。

Basically, I have to change the values of the array and do this 12000 times on a new array each time of length 12000. The "something interesting" code is merely looking up that index in another data structure and calling a setter. From my System time calculations, it should take me about 13 hours. I have 8 processors on my machine.

如何利用java的多线程功能?我特意寻找分区初始化和扫描数组的线程解决方案。使用线程的源代码将不胜感激。

How can I take advantage of java's multi-threading capabilities? I am specifically looking for thread solutions that partition up the initializing and scanning of the arrays. Source code using threads would be appreciated.

推荐答案

您可以在八个不同的线程中将其划分为这样的

You can divide this up among eight different threads doing something like this

public class Worker implements Runnable {
    final private int minIndex; // first index, inclusive
    final private int maxIndex; // last index, exclusive
    final private float[] data;

    public Worker(int minIndex, int maxIndex, float[] data) {
        this.minIndex = minIndex;
        this.maxIndex = maxIndex;
        this.data = data;
    }

    public void run() {
        for(int i = minIndex; i < maxIndex; i++) {
            if(data[i] >= 0.75) {
                // do something interesting
            }
        }
    }
}


// *** Main Thread ***
float[] data = new float[12000];
int increment = data.length / 8;
for(int i = 0; i < 8; i++) {
    new Thread(new Worker(i * increment, (i + 1) * increment, data)).start();
}

这会将数组划分为8个不同的线程。或者,另一种选择是:

This divides up the array among the 8 different threads. Or, another option is this:

public class Worker implements Runnable {
    final private BlockingQueue<Integer> queue;
    final private float[] data;

    public Worker(BlockingQueue<Integer> queue) {
        this.queue = queue;
        this.data = data;
    }

    public void run() {
        while(true) {
            int i = queue.take();
            float f = data[i];
            // do something interesting to f
        }
    }
}


// *** Main Thread ***
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
float[] data = new float[12000];
for(int i = 0; i < 8; i++) {
    new Thread(new Worker(queue, data)).start();
}
for(int i = 0; i < data.length; i++) {
    if (data[i] >= 0.75) {
        queue.offer(i);
    }
}

这使用一个线程迭代数组并查找有趣的数字,然后使用八个工作线程为有趣的数字做一些有趣的事情。我倾向于选择这种方法,因为第一种方法可能会导致一个工作线程必须处理一千个有趣的数字,而另一个工作线程只需要处理一些有趣的数字;这种方法确保每个线程需要处理大约相同数量的有趣数字。

This uses one thread to iterate through the array and find the interesting numbers, and then uses eight worker threads to do something interesting to the interesting numbers. I'd tend to prefer this approach, as it's possible with the first approach that one worker thread would wind up having to process a thousand interesting numbers while another worker thread only needs to process a few interesting numbers; this approach ensures that each thread needs to process approximately the same quantity of interesting numbers.

我省略了很多东西,比如如何使用执行程序以及如何关闭工作线程等 - 这是一个教程

I'm omitting a lot of stuff, like how to use Executors and how to shut down your worker threads etc - here's a tutorial on that.

编辑要获取代码并在8个主题上运行12000次,您需要执行以下操作:

Edit To take your code and run it 12000 times on 8 threads, you would do the following:

public class Worker implements Runnable {
    private final int numberOfIterations;
    private final float[] x = new float[12000];

    public Worker(int numberOfIterations) {
        this.numberOfIterations = numberOfIterations;
    }

    public void run() {
        for(int i = 0; i < numberOfIterations; i++) {
            Random random = new Random();

            for (int i = 0; i < x.length; i++) {
                x[i] = random.nextFloat();
            }

            for (int i = 0; i < x.length; i++) {
                if (x[i] >= 0.75) {
                    \\ do something interesting
                }
            }
        }
    }
}


// *** Main Thread ***
Thread[] threads = new Thread[8];
for(int i = 0; i < 8; i++) {
    threads[i] = new Thread(new Worker(12000/8));
    threads[i].start();
}
for(int i = 0; i < 8; i++) {
    threads[i].join();
}

八个线程中的每一个都将运行初始化浮点数组的1500次迭代,迭代浮点数组代码。然后 join 方法将等待线程完成。确保中的代码//做一些有趣的事情是线程安全的 - 你说你正在调用一个setter,所以要确保多个线程不会调用相同的setter,或者setter是同步的,或者你在setter中使用类似 AtomicInteger 的东西。如果你对它有任何疑问,请发布setter代码。

Each of the eight threads will run 1500 iterations of the "initialize float array, iterate through float array" code. The join method will then wait for the threads to finish. Be certain that the code in // do something interesting is thread-safe - you said that you're calling a setter, so be certain that multiple threads won't be calling the same setter, or else that the setter is synchronized, or else that you're using something like an AtomicInteger in the setter. Post the setter code if you have any doubts about it.

这篇关于使用多线程处理对Java数组进行分区和分析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆