Fork/Join Framework

Fork/Join consists of a special executor service and thread pool. The Fork/Join breaks a task down into smaller tasks that are forked (executed by different threads) from the pool. A task waits until joined (its subtasks finish). The following code shows how to multiply two matrixes via the Fork/Join Framework

 
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;

public class Main{
    public static void main(String[] args) {
        Matrix a = new Matrix(2, 3);
        a.setValue(0, 0, 1); // | 1 2 3 | 
        a.setValue(0, 1, 2); // | 4 5 6 | 
        a.setValue(0, 2, 3);
        a.setValue(1, 0, 4);
        a.setValue(1, 1, 5);
        a.setValue(1, 2, 6);
        Matrix b = new Matrix(3, 2);
        b.setValue(0, 0, 7); // | 7 1 | 
        b.setValue(1, 0, 8); // | 8 2 | 
        b.setValue(2, 0, 9); // | 9 3 | 
        b.setValue(0, 1, 1);
        b.setValue(1, 1, 2);
        b.setValue(2, 1, 3);
        Matrix c = new Matrix(2, 2);
        ForkJoinPool pool = new ForkJoinPool();
        pool.invoke(new Calc(a, b, c));
    }

}
class Calc extends RecursiveAction {

    private Matrix a, b, c;
    private int row;

    Calc(Matrix a, Matrix b, Matrix c) {
        this(a, b, c, -1);
    }

    Calc(Matrix a, Matrix b, Matrix c, int row) {
        if (a.getCols() != b.getRows()) {
            throw new IllegalArgumentException("rows/columns mismatch");
        }
        this.a = a;
        this.b = b;
        this.c = c;
        this.row = row;
    } 

    @Override
    public void compute() {
        if (row == -1) {
            List<Calc> tasks = new ArrayList<>();
            for (int row = 0; row < a.getRows(); row++) {
                tasks.add(new Calc(a, b, c, row));
            }
            invokeAll(tasks);
        } else {
            multiplyRowByColumn(a, b, c, row);
        }
    }

    void multiplyRowByColumn(Matrix a, Matrix b, Matrix c, int row) {
        for (int j = 0; j < b.getCols(); j++) {
            for (int k = 0; k < a.getCols(); k++) {
                c.setValue(row, j, (int)(c.getValue(row, j) +  a.getValue(row, k)* b.getValue(k, j)));
            }
        }
    }
}

class Matrix {
  private int[][] doubleArray;

  Matrix(int nrows, int ncols) {
    doubleArray = new int[nrows][ncols];
  }

  int getCols() {
    return doubleArray[0].length;
  }

  int getRows() {
    return doubleArray.length;
  }

  double getValue(int row, int col) {
    return doubleArray[row][col];
  }

  void setValue(int row, int col, int value) {
    doubleArray[row][col] = value;
  }
}