【问题标题】:ThreadPool quitting upon submit线程池在提交时退出
【发布时间】:2014-11-25 19:48:06
【问题描述】:

只要我向ThreadExecutor 提交Runnable,它就会退出,我不知道为什么。我已经跟踪了代码,但无济于事。有谁知道为什么会这样?

通过退出,我的意思是任务已提交并且它从不运行 Multiplier 类(运行方法) - 第一次提交到 ThreadPool 只是用退出代码 0 关闭整个程序。

public class Main {
    public static void main(String[] args) {

        /**
        * 0: threads
        * 1: matrix A
        * 2: matrix B
        * 3: matrix C -- output file
        */
        Object[] parsedArgs = CommandLineArgParser.getArguments(args); // strip arguments -- contains help and exit upon incorrect entries

        try {
            // Create thread pool
            int threads = Integer.parseInt((String) parsedArgs[0]);
            ExecutorService threadPool;
            if (threads > 0) {
                threadPool = Executors.newFixedThreadPool(threads*2); // create twice as many threads as OS cores
            }else
            throw new InputMismatchException("Threads must be an Integer");

            // Create matrices:
            Matrix m1 = getMatrix((String) parsedArgs[1]);
            Matrix m2 = getMatrix((String) parsedArgs[2]);
            Matrix m3 = null;
            try {
                m3 = m1.multiply(m2, threadPool);
                } catch (ExecutionException exE) {
                System.exit(1);
                } catch (InterruptedException iE) {
                System.exit(1);
            }
            threadPool.shutdown();

            try {
                threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
                } catch (InterruptedException e) {
                System.out.println("The operation is taking too long. Exiting.");
                System.exit(1);
            }

            // Write to file!
            m3.writeToFile((String)parsedArgs[3]);

            }catch (ArrayIndexOutOfBoundsException arrayOutBounds) {
            // means that correct arguments were not passed in. print them.

        }

    }

    public static Matrix getMatrix(String filePath) {
        try {
            return MatrixCreator.createMatrix(filePath);
            } catch (IOException ioE) {
            // Matrix could not be found in filesystem
            System.out.println("The matrix path (" + filePath +") supplied could not be found in the filesystem. If you have not already, try an absolute path.");
            System.exit(0); //exit so that user may re-enter
        }
        return null; // should never happen
    }
}

public class Matrix {

    int rows, cols; // number of rows and columns in matrix, respectively.
    Double [][] matrix;

    public Matrix(int rows, int cols) {
        this.rows = rows;
        this.cols = cols;
        matrix = new Double[rows][cols]; // create matrix of proper size
    }

    /**
    * Inserts value into matrix
    * @param row row in which to insert element
    * @param col column in which to insert element
    * @param val
    */
    public void insertValue(int row, int col, double val) {
        matrix[row][col] = val; // no error checking applied for column or row -- would reduce speed when inserting thousands of values
    }

    /**
    * A is THIS matrix. <code>multiply()</code> computes AB = C.
    * @param B matrix by which to multiply
    * @param threadPool thread pool to use
    * @return matrix C
    */
    public Matrix multiply(Matrix B, ExecutorService threadPool) throws ExecutionException, InterruptedException {
        System.out.println("In multiply..");
        Matrix C = new Matrix(this.rows, B.cols); // create matrix C of appropriate size
        ArrayList<Future<?>> futures = new ArrayList<Future<?>>();
        for (int i = 0; i < C.rows; i++) {
            System.out.println(C.rows);
            for (int j = 0; j < C.cols; j++) {
                System.out.println(C.cols);
                System.out.println("Here");
                futures.add(threadPool.submit(new Multiplier(this.getColumnsOfRow(i), B.getRowsOfColumn(j), C, i, j)));
            }
        }
        for (Future<?> f : futures) {
            f.get();
        }
        return C;
    }

    private Double[] getRowsOfColumn(int column) {
        Double[]  rowsOfColumn = new Double[rows];
        for (int i = 0; i < rows; i++) {
            rowsOfColumn[i] = this.matrix[i][column];
        }
        return rowsOfColumn;
    }

    private Double[] getColumnsOfRow(int row) {
        Double[] columnsOfRow = new Double[cols];
        for (int i = 0; i < cols; i++) {
            columnsOfRow[i] = this.matrix[row][cols];
        }
        return columnsOfRow;
    }

    // make string...
    public String toString() {
        String s = "";
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                s += matrix[i][j] + ", ";
            }
            s += "\n";
        }
        return s;
    }

    // write file to path provided
    public void writeToFile(String filePath) {
        System.out.println("Saving to: " + filePath);
        try {
            BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, false));
            for (int i = 0; i < rows; i++) {
                for (int j = 0; j < cols; j++) {
                    if (j == cols - 1) {
                        writer.write("" + matrix[i][j] + "\n");
                        } else {
                        writer.write("" + matrix[i][j] + ",");
                    }
                }
            }
            writer.close();
            } catch (IOException ioE) {
            System.out.println("Could not save file to specified location. Printing stacktrace:");
            ioE.printStackTrace();
            System.exit(1);
        }
        System.out.println("Matrix successfully written to file: " + filePath);
    }

    class Multiplier implements Runnable {

        Double[] ARow, BCol;
        Matrix C;
        int insertRow, insertCol;
        /**
        * This will method will multiply the row of matrix A and the
        * column of matrix B on a thread.  The result will be put into
        * matrix C at the specified locations.
        * @param ARow the Row to be multiplied by the column of matrix B
        * @param BCol the Column to be multiplied by the row of matrix A
        * @param C the matrix which will hold the resultant of the two operations.
        * @param insertRow  the row of matrix C in which to insert the multiplication
        * @param insertCol  the column of matrix C in which to insert the multiplication
        */
        public Multiplier(Double[] ARow, Double[] BCol, Matrix C, int insertRow, int insertCol) {
            System.out.println("We are here!");
            this.ARow = ARow;
            this.BCol = BCol;
            this.C = C;
            this.insertRow = insertRow;
            this.insertCol = insertCol;
        }

        @Override
        public void run() {
            double sum = 0;
            for (int i = 0; i < ARow.length; i++) {
                sum += ARow[i]*BCol[i];
            }
            C.insertValue(insertRow,insertCol,sum);
        }
    }

使用的命令行参数-t 8 -m1 /Users/me/Desktop/Matrices/matrixA.mat -m2 /Users/me/Desktop/Matrices/matrixB.mat -o /Users/me/Desktop/Matrices/output.mat

【问题讨论】:

  • 你说的退出是什么意思?
  • 它没有创建乘数类并且程序在此之前退出
  • 好像抛出了异常?
  • 我没有发现任何异常
  • 你必须向我们展示更多。就目前而言,您所展示的任何内容都不会导致您所描述的内容。

标签: java multithreading java.util.concurrent


【解决方案1】:

您的程序不能只是提交作业并终止。因此,一旦您提交了所有作业,您必须执行以下操作:

Future<Void> result = threadPool.submit(new Multiplier(this.getColumnsOfRow(i), 
                                                B.getRowsOfColumn(j), C, i, j));
result.get()

这将确保您的代码在终止主线程之前等待线程完成。

此外,您还可以查看 CompletionService。例如,请参阅this

[基于编辑]

public Matrix multiply(Matrix B, ExecutorService threadPool) {
    System.out.println("In multiply..");
    Matrix C = new Matrix(this.rows, B.cols); // create matrix C of appropriate size
    ArrayList<Future<?>> futures = new ArrayList<Future<?>>();
    for (int i = 0; i < C.rows; i++) {
        System.out.println(C.rows);
        for (int j = 0; j < C.cols; j++) {
            System.out.println(C.cols);
            System.out.println("Here");
            futures.add(threadPool.submit(new Multiplier(this.getColumnsOfRow(i), B.getRowsOfColumn(j), C, i, j)));
        }
    }
    for(Future<?> future: futures) {
        future.get()
    }
    return C;
}

这将确保您在实际提取乘法结果之前等待线程完成。您的代码可能需要为此进行一些重构。

【讨论】:

  • 为什么在他们当前的设置中需要这些?
  • 我假设这是用于学习 Java 并发包的虚拟代码,而不是代码审查。
  • 这是我正在编写的伪代码,但这不起作用。 一旦任务提交给 ExecutorService,程序就会退出。我已经发布了所有适用的代码。
  • 问题是,如果您不执行 get(),您将不知道是否有任何线程因异常终止或正常终止。因此,最好使用可调用对象,并从可调用对象的返回中收集线程的成功。可能不允许同时修改您的 Matrix 类(这是您对 Matrix C 所做的),并且所有线程都立即因错误而终止。由于您的 Runnable 没有打印任何日志,因此在您通过 Futures 单独收集线程状态之前,无法知道。
  • 我没有任何未来可以通过
【解决方案2】:

你的代码在这里

private Double[] getColumnsOfRow(int row) {
    Double[] columnsOfRow = new Double[cols];
    for (int i = 0; i < cols; i++) {
        columnsOfRow[i] = this.matrix[row][cols];
    }
    return columnsOfRow;
}

将使用值为20cols。但是您的 matrix 被创建为

matrix = new Double[rows][cols]; // 20 x 20

所以最后一个索引是 19。这会抛出一个 ArrayIndexOutOfBoundsException,您会吞下它,并且您的应用以状态码 0 结束,因为该方法正常返回。

改成

columnsOfRow[i] = this.matrix[row][i];

【讨论】:

  • Sotirios,谢谢。很抱歉浪费您的时间。愚蠢的错误。
  • @user2243357 如果您现在删除您的接受,您可以删除您的问题。这些事情都会发生。你应该(几乎)永远不要吞下异常而不至少记录它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-17
  • 1970-01-01
  • 2021-12-28
  • 1970-01-01
  • 2016-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多