0

I have a two-dimensional cellular automata. In some cells there may be an actor (agent). Each actor is a thread. I need to move actor based on the 9 cells around the actor's cell. I want to do this concurrently so the actor in a cell (4,5) can use neighbors cells (3,4), (4,4), (5,4), (3,5), (5,5), (3,6), (4,6), (5,6) and no other actors can use this cells. If some actor has these cells in his neighborhood, he has to wait until the first actor moved. But I want to allow moving the actor, who has no common neighborhood, concurrently. So the actor in (4,5) can move at the same time as an actor in (10,5) because they have no common neighborhood.

What is the best solution of that? Can you propose something?

michalk93
  • 189
  • 2
  • 10
  • Several questions about what should be implemented: 1. When Thread moves to the new cell, show it sleep there for fixed time (let's say 1 sec) or not? 2. Do you need UI visualization (Swing)? In this case you could mark 'waiting to move' threads red, and moving/sleeping threads green. As an option for implementation, you may create a matrix of cells `Cell[][] matrix`. Whenever Thread goes to the next cell it owns the monitor on this cell: `synchronized(matrix[i][j]) { Thread.sleep(1000); }` – Anton Dovzhenko Dec 27 '16 at 08:19

1 Answers1

1

The rough idea is below.

  1. Create matrix of Cell objects, which will be used for synchronization
  2. Assign Actors to the cells
  3. Whenever Actor moves to another cell it must get a monitor on the cell

Note that the cell, from which Actor starts to move, is not protected in the code below. Also, what would you expect if every cell is populated has an Actor?

import java.util.ArrayList;
import java.util.List;

public class CellularAutomata {

    public static void main(String ... args) throws InterruptedException {
        final int rows = 5;
        final int cols = 5;
        Cell[][] matrix = new Cell[rows][cols];
        List<Actor> actors = new ArrayList<>();
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                matrix[i][j] = new Cell();
                //populate actors
                if ((i + j) % 2 == 0) {
                    Actor actor = new Actor(matrix, i, j);
                    actor.setName(String.format("Actor %d %d", i, j));
                    actors.add(actor);
                }
            }
        }
        for (Actor actor : actors) {
            actor.start();
        }
        for (Actor actor : actors) {
            actor.join();
        }
    }

    public static class Cell {}

    public static class Actor extends Thread {

        private final static int[][] circleMoves = {
                {-1, -1}, {-1, 0}, {-1, 1}
                , {0, 1}, {1, 1}, {1, 0}
                , {1, -1}, {0, -1}, {0, 0}
        };
        private final Cell[][] matrix;
        private final int row;
        private final int col;

        public Actor(Cell[][] matrix, int row, int col) {
            this.matrix = matrix;
            this.row = row;
            this.col = col;
        }

        @Override
        public void run() {
            for (int i = 0; i < circleMoves.length; i++) {
                int nextRow = row + circleMoves[i][0];
                int nextCol = col + circleMoves[i][1];
                if (nextRow >= 0 && nextRow < matrix.length
                        && nextCol >= 0 && nextCol < matrix[nextRow].length) {
                    Cell targetCell = matrix[nextRow][nextCol];
                    System.out.println(Thread.currentThread().getName() + " waiting for cell (" + nextRow + ";" + nextCol + ")");
                    synchronized (targetCell) {
                        try {
                            System.out.println(Thread.currentThread().getName() + " moved to cell (" + nextRow + ";" + nextCol + ")");
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            throw new IllegalStateException(e);
                        }
                    }
                }
            }
        }

    }

}
Anton Dovzhenko
  • 2,399
  • 11
  • 16