Основной поток Java отправляет сигнал, а затем ожидает другие несинхронизированные потоки - PullRequest
0 голосов
/ 02 июня 2018

Я изучаю потоки в Java и пытаюсь сделать что-то вроде этого:
У меня есть матрица со значениями, и для каждой ячейки в матрице есть назначенный ей поток, который обновляетзначения (в соответствии с игрой жизни Конвея ).Все потоки должны обновлять значения матрицы один раз, а затем, когда все они будут завершены, основной поток отобразит обновленную матрицу, а затем спросит пользователя, должен ли он также рассчитать следующий шаг, что означает повторение тех же самых вычислений заново.,
Теперь я написал почти весь базовый код, включая потоки и то, как они обновляют ячейку, за которую они отвечают, но я не могу найти способ, чтобы основной поток уведомил все остальные потоки о пробуждениивстать, сделать свою работу, а затем вернуться в сон и получить от них уведомление после того, как все они закончили свою работу на данный момент.Я пытался использовать методы wait () и notify () / notifyAll (), но они предназначены только для синхронизированных методов, которые мне не нужно реализовывать в коде (поскольку я использую две матрицы, чтобы убедиться,что сначала все потоки обновляют свою соответствующую ячейку, и только тогда текущая матрица станет матрицей следующего поколения).
Вот метод run () для потоков:

public void run(boolean[][] currentGenMatrix) {
    updateLifeMatrix(currentGenMatrix);
    while(true) {
        try {
            wait();    // Wait for the next step before starting
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        updateLifeMatrix(m_nextGenMatrix);    // Update the current matrix to be the "next generation matrix" from the previous generation
        int neighbours = checkNeighbours(currentGenMatrix);
        m_nextGenMatrix[this.m_heightIndex][this.m_widthIndex] = setNewLifeOrDeath(neighbours, getCurrentLifeOrDeath(currentGenMatrix));    // Update the "next generation matrix" cell assigned to this thread
    }
}

Во время инициализации матрицы я запускаю все потоки после их создания, а затем они сначала ждутуведомление, прежде чем сделать первый шаг.Я также читал о мониторах, чтобы понять, нужно ли мне это, но примеры, которые я видел в Интернете, не вписываются в мой код.

1 Ответ

0 голосов
/ 02 июня 2018

Вот простой пример использования AcyclicBarrier с двумя рабочими потоками, управляемыми потоком координатора (поток, выполняющий метод main).Два барьера используются;все рабочие потоки ожидают начала барьера.Когда координатор ожидает этого барьера, барьер разрушается, и рабочие начинают работать.Чтобы скоординировать завершение работы, все N рабочих, а также координатор должны прибыть к конечному барьеру и сломать его (ждать его).

package stackOv;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class UseBarrier {

  public static void main(String[] args) throws Exception {
    int numThreads = 2 ;
    // one slot for the coordinator
    CyclicBarrier barrierStart = new CyclicBarrier(numThreads+1);
    CyclicBarrier barrierEnd = new CyclicBarrier(numThreads+1);

    Runnable work1 = new WorkerThread(barrierStart, barrierEnd, "work-0");
    Runnable work2 = new WorkerThread(barrierStart, barrierEnd, "work-1");
    new Thread(work1).start();
    new Thread(work2).start();

    while (true) {
      System.out.println("main: start");
      Thread.sleep(1000);
      barrierStart.await();
      System.out.println("waiting for workers..");
      barrierEnd.await();
      System.out.println("work finished, continue");
      Thread.sleep(1000);
    }
  }
}

class WorkerThread implements Runnable {
  private CyclicBarrier startWork;
  private CyclicBarrier endWork;
  private String name;
  public WorkerThread(CyclicBarrier startWork, CyclicBarrier barrier, String name) {
    this.startWork = startWork;
    this.endWork = barrier;
    this.name = name;
  }

  @Override
  public void run() {
    while (true) {
      try {
        System.out.println("worker "+name+": waiting");
        startWork.await();
        System.out.println("working.. "+name);
        Thread.sleep(1000);
        System.out.println("worker "+name+": done");
        endWork.await();
      } catch (BrokenBarrierException | InterruptedException e) {
        // depending on your application, you can either manage the
        // brokenBarrier exception, close your program (or ignore it)
      }
    }
  }
}
...