如何在java中使用多线程对记录列表进行排序?

如何在java中使用多线程对记录列表进行排序?,java,multithreading,Java,Multithreading,我正在自学java多线程。我的虚拟示例是,我有一个需要排序的大型记录列表(一个2D数组)。单线程方法是通过记录和排序列表使用循环。我想对我的程序进行多线程处理,以使用固定数量的线程对列表进行排序,在本例中为2。一个线程将对列表的前一半进行排序,第二个线程将对剩余的一半进行排序。然后我想输出结果,现在排序的记录列表 如何创建工作线程池并对记录列表进行排序?我是否需要担心数据是共享资源?如何将每个线程的结果返回到原始记录列表?下面是我的代码 import java.util.*; class Ru

我正在自学java多线程。我的虚拟示例是,我有一个需要排序的大型记录列表(一个2D数组)。单线程方法是通过记录和排序列表使用循环。我想对我的程序进行多线程处理,以使用固定数量的线程对列表进行排序,在本例中为2。一个线程将对列表的前一半进行排序,第二个线程将对剩余的一半进行排序。然后我想输出结果,现在排序的记录列表

如何创建工作线程池并对记录列表进行排序?我是否需要担心
数据
是共享资源?如何将每个线程的结果返回到原始记录列表?下面是我的代码

import java.util.*;

class RunnableProcess implements Runnable {
  private int[] data;

  public RunnableProcess(int[] data) {
      this.data = data;
  }

  public void run() {
    try {

      // sort the records this thread has access to
      for (int i = 0; i < data.length; i++) {
        Arrays.sort(data[i]);
      }

    } catch(Exception ex) {
        ex.printStackTrace();
    }
  }
}

class BigData {

  static int[][] data = new int[1000][1000];

  public static void main(String [] args) {


    // Create records 
    for (int i = 0; i < data.length; i++) {
      for (int j = 0; j < data[0].length; j++) {
        data[i][j] = new Random().nextInt(999);
      }
    }

    // Call on two threads to sort the data variable
    // ExecutorService executor = Executors.newFixedThreadPool(2);


   // Python type of idea: Pass half the records to each thread and start
   // java doesn't support this so what is the java way of doing this?

   // Thread thread = new Thread(new RunnableProcess(data[:499]));
   // thread.start();

   // Thread thread = new Thread(new RunnableProcess(data[499:]));
   // thread.start();

  }
}
import java.util.*;
类RunnableProcess实现Runnable{
私有int[]数据;
公共RunnableProcess(int[]数据){
这个数据=数据;
}
公开募捐{
试一试{
//对该线程有权访问的记录进行排序
对于(int i=0;i

我对解决这个问题的最佳方法持开放态度。

Java不支持以与python相同的方式对本机数组进行切片。我们可以使用
ArrayList
接近

首先是一个旁白。随机数据生成效率很低。您正在为生成的每个随机数创建一个新的
Random
number生成器对象。您只需要一个发电机,如下所示:

Random rnd = new Random();                     // Only created once
for (int i = 0; i < data.length; i++) {
    for (int j = 0; j < data[0].length; j++) {
        data[i][j] = rnd.nextInt(999);
    }
}
请注意,这不会复制数组中的值。它创建数组的
列表
视图。对
数据中存储的值的任何更改都将反映在
记录中,反之亦然

我们这样做,因此我们可以使用该方法将列表拆分为两个视图

List<int[]> first_half = records.subList(0, 500);
List<int[]> second_half = records.subList(500, 1000);
现在,我们将数据划分为两个独立的集合,并有一个
RunnableProcess
,可以对每个集合进行操作。现在,我们可以开始多线程处理了

ExecutorService executor = Executors.newFixedThreadPool(2);
此执行器服务创建一个包含两个线程的池,并将在提交给此执行器的后续任务中反复重用这些线程。因此,您不需要创建和启动自己的线程。遗嘱执行人将负责此事

executor.submit(new RunnableProcess(first_half));
executor.submit(new RunnableProcess(second_half));
由于我们想知道这些任务何时完成,因此需要保存从
executor.submit()返回的
Future

最后,您需要
#shutdown()
执行器,否则您的程序可能无法正常终止

executor.shutdown();

完整示例:

List<int[]> records = Arrays.asList(data);
List<int[]> first_half = records.subList(0, 500);
List<int[]> second_half = records.subList(500, 1000);

ExecutorService executor = Executors.newFixedThreadPool(2);

try {
    Future<?> task1 = executor.submit(new RunnableProcess(first_half));
    Future<?> task2 = executor.submit(new RunnableProcess(second_half));

    task1.get();  // Wait for first task to finish ...
    task2.get();  // ... as well as the second task to finish.
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

executor.shutdown();
List记录=数组.asList(数据);
列表前半部分=记录。子列表(0500);
列表后半部分=记录。子列表(5001000);
ExecutorService executor=Executors.newFixedThreadPool(2);
试一试{
Future task1=executor.submit(新的RunnableProcess(前半部分));
Future task2=executor.submit(新的RunnableProcess(后半段));
task1.get();//等待第一个任务完成。。。
task2.get();/…以及要完成的第二个任务。
}捕获(中断异常|执行异常e){
e、 printStackTrace();
}
executor.shutdown();

我是否需要担心数据是共享资源

在本例中,不是。您的
数据是一个数组数组。每个线程仅引用
数据
数组(作为
列表
),以获取对
int[]
记录的引用。
数据
数组本身不可修改;只有记录被删除,但每个记录仅由一个线程修改

如何将每个线程的结果返回到原始记录列表


由于正在“就地”对记录进行排序,因此
数据
变量已包含已排序记录的数组。调用
Future#get()
可确保每个
线程
都已完成其处理,以便可以再次从主线程安全访问数据。

查看
ArrayList
,您已经忘记了需要执行的第三步-合并排序结果。查看合并排序算法!
Future<?> task1 = executor.submit(new RunnableProcess(first_half));
Future<?> task2 = executor.submit(new RunnableProcess(second_half));
task1.get();  // Wait for first task to finish ...
task2.get();  // ... as well as the second task to finish.
executor.shutdown();
List<int[]> records = Arrays.asList(data);
List<int[]> first_half = records.subList(0, 500);
List<int[]> second_half = records.subList(500, 1000);

ExecutorService executor = Executors.newFixedThreadPool(2);

try {
    Future<?> task1 = executor.submit(new RunnableProcess(first_half));
    Future<?> task2 = executor.submit(new RunnableProcess(second_half));

    task1.get();  // Wait for first task to finish ...
    task2.get();  // ... as well as the second task to finish.
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

executor.shutdown();