import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Queue; //import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; //import java.util.concurrent.LinkedBlockingQueue; public class GameOfLife implements AutoCloseable { public class GOLThread extends Thread { //private BlockingQueue workQueue = new LinkedBlockingQueue(); private Queue workQueue = new LinkedList(); private boolean exiting = false; private boolean pointsProcessed = false; private GameOfLife parent; private Object _lock = new Object(); public GOLThread(GameOfLife gol) { parent = gol; } public void setExiting() { exiting = true; } public void setPointsProcessed() { pointsProcessed = true; } public void addPoint(Point p) { synchronized(_lock) { workQueue.add(p); } } @Override public void run() { while (!exiting) { if (workQueue.isEmpty()) { if (pointsProcessed) { parent.canStep.countDown(); pointsProcessed = false; } try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } else { Point p; synchronized(_lock) { p = workQueue.poll(); } parent.getEnv().increment(p); } } } } private int numThreads; private List threads = new ArrayList(); private Environment curEnv; GameOfLife(Environment env) { curEnv = env; } synchronized void setThreadCount(int nThread) throws InterruptedException { numThreads = nThread; for (int i = 0; i < threads.size(); i++) threads.get(i).exiting = true; for (int i = 0; i < threads.size(); i++) threads.get(i).join(); threads.clear(); for (int i = 0; i < numThreads; i++) { threads.add(new GOLThread(this)); threads.get(threads.size() - 1).start(); } } public Environment getEnv() { return curEnv; } public CountDownLatch canStep; public void step() throws InterruptedException { canStep = new CountDownLatch(numThreads); int i = 0; for (Point p : curEnv.livingCells) { threads.get(i % threads.size()).addPoint(p); i++; } for (i = 0; i < threads.size(); i++) threads.get(i).setPointsProcessed(); canStep.await(); curEnv = curEnv.next(); } public void start() { numThreads = 1; threads.add(new GOLThread(this)); threads.get(threads.size() - 1).run(); } @Override public void close() throws Exception { for (int i = 0; i < threads.size(); i++) threads.get(i).exiting = true; for (int i = 0; i < threads.size(); i++) threads.get(i).join(); } }