ThreadPool在提交时退出

时间:2014-10-01 02:57:26

标签: java multithreading java.util.concurrent

一旦我向Runnable提交ThreadExecutor,它就会退出,我无法弄清楚原因。我已经跟踪了代码,但无济于事。有谁知道为什么会这样?

退出,我的意思是提交任务,它永远不会运行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

的命令行参数

2 个答案:

答案 0 :(得分:0)

您的计划无法提交作业并终止。因此,一旦提交了所有工作,您就必须执行以下操作:

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;
}

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

答案 1 :(得分:0)

您的代码

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;
}

将使用cols,其值为20。但是您的matrix已创建为

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

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

将其更改为

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