Breaking Down Tasks into Discrete Units of Work with Fork/Join framework - Java Thread

Java examples for Thread:Fork Join

Description

Breaking Down Tasks into Discrete Units of Work with Fork/Join framework

Demo Code

import java.awt.Color;
import java.awt.Component;
import java.lang.reflect.InvocationTargetException;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;

public class Main {

  public static void main(String[] args) throws Exception {
    boolean[][] lifeBoard = new boolean[50][50];
    final LifeTableModel model = new LifeTableModel(lifeBoard);
    final JTable lifeTable = new JTable();

    JFrame frame = new JFrame("Game of Life");
    lifeTable.setModel(model);// ww w.j  a v a 2  s.  co  m
    lifeTable.setDefaultRenderer(Boolean.class, new LifeTableCellRenderer());
    frame.setContentPane(new JScrollPane(lifeTable));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(1000, 1000);
    frame.setVisible(true);

    for (boolean[] lifeBoard1 : lifeBoard) {
      for (int col = 0; col < lifeBoard[0].length; col++) {
        lifeBoard1[col] = new Random().nextBoolean();
      }
    }
   
    model.fireTableDataChanged();
    ForkJoinPool pool = new ForkJoinPool();
    while (true) {
      final boolean[][] newBoard = new boolean[lifeBoard.length][lifeBoard[0].length];
      GameOfLifeAdvancer advancer = new GameOfLifeAdvancer(lifeBoard, 0, 0,
          lifeBoard.length - 1, lifeBoard[0].length - 1, newBoard);
      pool.invoke(advancer);
      SwingUtilities.invokeAndWait(() -> {
        model.setBoard(newBoard);
        lifeTable.repaint();
      });
      lifeBoard = newBoard;
    }
  }
}
class LifeTableCellRenderer extends JLabel implements TableCellRenderer {
  public LifeTableCellRenderer() {
    this.setOpaque(true);
  }

  @Override
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    if ((Boolean) value) {
      this.setBackground(Color.black);
    } else {
      this.setBackground(Color.white);
    }
    return this;
  }
}
class LifeTableModel extends AbstractTableModel {
  private boolean[][] lifeBoard;

  public LifeTableModel(boolean[][] lifeBoard) {
    this.lifeBoard = lifeBoard;
  }

  @Override
  public String getColumnName(int column) {
    return null;
  }

  @Override
  public int getRowCount() {
    return lifeBoard.length;
  }

  @Override
  public int getColumnCount() {
    return lifeBoard[0].length;
  }

  @Override
  public Object getValueAt(int rowIndex, int columnIndex) {
    return lifeBoard[rowIndex][columnIndex];
  }

  @Override
  public Class<?> getColumnClass(int columnIndex) {
    return Boolean.class;
  }

  public void setBoard(boolean[][] newBoard) {
    this.lifeBoard = newBoard;
  }
}
class GameOfLifeAdvancer extends RecursiveAction {
  private boolean[][] originalBoard;
  private boolean[][] destinationBoard;
  private int startRow;
  private int endRow;
  private int endCol;
  private int startCol;

  GameOfLifeAdvancer(boolean[][] originalBoard, int startRow, int startCol,
      int endRow, int endCol, boolean[][] destinationBoard) {
    this.originalBoard = originalBoard;
    this.destinationBoard = destinationBoard;
    this.startRow = startRow;
    this.endRow = endRow;
    this.endCol = endCol;
    this.startCol = startCol;
  }

  private void computeDirectly() {
    for (int row = startRow; row <= endRow; row++) {
      for (int col = startCol; col <= endCol; col++) {
        int numberOfNeighbors = getNumberOfNeighbors(row, col);
        if (originalBoard[row][col]) {
          destinationBoard[row][col] = true;
          if (numberOfNeighbors < 2)
            destinationBoard[row][col] = false;
          if (numberOfNeighbors > 3)
            destinationBoard[row][col] = false;
        } else {
          destinationBoard[row][col] = false;
          if (numberOfNeighbors == 3)
            destinationBoard[row][col] = true;
        }
      }
    }
  }

  private int getNumberOfNeighbors(int row, int col) {
    int neighborCount = 0;
    for (int leftIndex = -1; leftIndex < 2; leftIndex++) {
      for (int topIndex = -1; topIndex < 2; topIndex++) {
        if ((leftIndex == 0) && (topIndex == 0))
          continue; // skip own
        int neighbourRowIndex = row + leftIndex;
        int neighbourColIndex = col + topIndex;
        if (neighbourRowIndex < 0)
          neighbourRowIndex = originalBoard.length + neighbourRowIndex;
        if (neighbourColIndex < 0)
          neighbourColIndex = originalBoard[0].length + neighbourColIndex;
        boolean neighbour = originalBoard[neighbourRowIndex
            % originalBoard.length][neighbourColIndex % originalBoard[0].length];
        if (neighbour)
          neighborCount++;
      }
    }
    return neighborCount;
  }

  @Override
  protected void compute() {
    if (getArea() < 20) {
      computeDirectly();
      return;
    }
    int halfRows = (endRow - startRow) / 2;
    int halfCols = (endCol - startCol) / 2;
    if (halfRows > halfCols) {
      // split the rows
      invokeAll(new GameOfLifeAdvancer(originalBoard, startRow, startCol,
          startRow + halfRows, endCol, destinationBoard),
          new GameOfLifeAdvancer(originalBoard, startRow + halfRows + 1,
              startCol, endRow, endCol, destinationBoard));
    } else {
      // split the columns
      invokeAll(new GameOfLifeAdvancer(originalBoard, startRow, startCol,
          endRow, startCol + halfCols, destinationBoard),
          new GameOfLifeAdvancer(originalBoard, startRow, startCol + halfCols
              + 1, endRow, endCol, destinationBoard));
    }

  }

  private int getArea() {
    return (endRow - startRow) * (endCol - startCol);
  }

}

Related Tutorials