且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用多线程处理对Java数组进行分区和分析

更新时间:2021-07-30 23:15:57

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

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.