java - 带有线程的表的总和

标签 java multithreading

我正在尝试对带有线程的表进行求和。我正在创建一个具有给定长度的表,然后尝试使用给定的线程名称创建一个总和。

根据索引,每个线程都占用表的一部分。

例如:

3 个线程上包含 12 个元素的表:

0 个线程获取 [0, 3, 6, 9] 个元素

1 个线程获取 [1, 4, 7, 10] 个元素

2 个线程获取 [2, 5, 8, 11] 个元素

线程对这些数字进行求和,然后返回结果。之后,我将所有内容汇总在一起,并得到结果。

这是我的单个 Callable 对象实现:

public class TableSumThread implements Callable<Integer> {

private int indeks;
private int[] table;

public TableSumThread(int indeks, int[] table) {
    this.indeks = indeks;
    this.table = table;
}


@Override
public Integer call() throws Exception {
    int iter = indeks;
    int sum = 0;
    while(iter < table.length) {
        sum += table[iter];
        iter += indeks;
    }
    return sum;
}

}

这是我的“执行者”:

public class TableSumExecutor {
private int[] table;
private int executors;

public Integer execute() {
    ExecutorService executorService = Executors.newFixedThreadPool(executors);
    List<Future<Integer>> results = new ArrayList<Future<Integer>>(executors);

    for (int i = 0; i < executors; i++) {
        Callable<Integer> task = new TableSumThread(i, table);
        results.add(executorService.submit(task));
    }
    System.out.println("After creating all threads.");
    int suma = sum(results);
    return suma;
}

private int sum(List<Future<Integer>> results) {
    int sum = 0;
    for (int i = 0; i < results.size(); i++) {
        try {
            sum += results.get(i).get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
    return sum;
}

主要:

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    System.out.println("Table length: ");
    int nTable = scanner.nextInt();
    System.out.println("Threads number: ");
    int nThreads = scanner.nextInt();

    Random random = new Random();
    int[] tablica = new int[nTable];
    for (int i = 0 ; i < tablica.length ; i++)
        tablica[i] = Math.abs(random.nextInt() % 9 + 1);

    TableSumExecutor tableSumExecutor = new TableSumExecutor(tablica, nThreads);
    int result = tableSumExecutor.execute();

    System.out.println("And the result is: " + result);
}

一切都很好,线程执行所有任务,但程序阻塞:

sum += results.get(i).get();

我没有收到任何异常,它只是阻塞。我也在调试器上检查过它。全部任务已完成,等待最后一步结果。

我可能没有正确使用 Future 类型的 get() ?

编辑。 好吧,我解决了一个问题。但计划毕竟还没有结束。当我在主 executorService.isShutdown() 中显示结果后进行检查时,它是错误的。我应该手动终止所有线程,还是应该自动终止?

最佳答案

在这行代码中:

Callable<Integer> task = new TableSumThread(i, table);

在 for 循环的第一次迭代中,“i”为 0。因此您创建了 indeks = 0 的 TableSumThread 对象。因此在此循环中:

int iter = indeks;
int sum = 0;
while(iter < table.length) {
    sum += table[iter];
    iter += indeks;
}

您不增加 iter 变量,这是无限循环。 这就是为什么你的第一个线程永远不会结束并阻塞主线程的执行(因为 future 对象上的 get() 会阻塞操作)。您可以尝试传递两个变量 - 起始索引和迭代(在您的情况下 - 常量 3)。类似 new TableSumThread(i, 3, table) 之类的东西。 希望这会有所帮助。

关于java - 带有线程的表的总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36068949/

相关文章:

java - 为什么我的线程失败时不会超时?

c++ - std::thread 在我调用 join() 之前是否运行?

java - 从两个单独的传入请求注入(inject)数据

C++ 多线程 : terminate after throwing an instance of 'std::length_error'

java - 如何使用 LUNA HSM 签署 PDF 文档?

java - 折扣销售图形用户界面

java - Hibernate 过滤器可以与条件查询一起使用吗?

java - 线程共享的 ReentrantLock 似乎不支持锁定

java - 如何在 java 中轻松切换导入源?

java - 读取xml文件时出现空指针异常