2017-02-22 1 views
0

나는 체크 포인트가있는 마라톤 선수를 보여주는 프로그램을 만들고 싶습니다. 5 명의 주자가 생성되고 첫 번째 체크 포인트에 도달하는 데 소요되는 시간이 임의로 늘어납니다. 주자는 모든 다른 주자가 체크 포인트에 도달 할 때까지 검사 점에서 멈춰야합니다. 2 개의 체크 포인트와 결승선이 있습니다. 여기 다른 유형의 다른 작업이 완료 될 때까지 Runnable을 일시 중지하는 방법은 무엇입니까?

내가이 구현하는 가장 좋은 방법이 될 것이라고 생각 몇 가지 기본적인 코드 :

public class Main { 
public static void main(String[] args) { 
    int i = 1; 
    Runner[] runners = new Runner[5]; 

    //Create 5 Runners 
    for (Runner runner : runners) { 
     runner = new Runner(i++); 
     runner.run(); 
    } 

    //Wait for runners to arrive at 1st checkpoint 
    for (Runner runner : runners) { 
     runner.arrivedAt1stCheckpoint(); 
    } 

    //Wait for runenrs to arrive at 2nd checkpoint 
    for (Runner runner : runners) { 
     runner.arrivedAt2ndCheckpoint(); 
    } 

    //Wait for runners to finish race 
    for (Runner runner : runners) { 
     runner.finishedRace(); 
    } 
}} 

public class Runner implements Runnable { 

    public final int runnerID; 
    Random randomGenerator = new Random(); 

    public Runner(int i) { 
     this.runnerID = i; 
    } 

    @Override 
    public void run() { 
     System.out.printf("Runner %d exists\n", runnerID); 
    } 

    public boolean arrivedAt1stCheckpoint() { 
     sleepThread(); 
     System.out.printf("Runner %d arrived at 1st checkpoint\n", runnerID); 
     return true; 
    } 

    public boolean arrivedAt2ndCheckpoint() { 
     System.out.printf("Runner %d arrived at 2nd checkpoint\n", runnerID); 
     sleepThread(); 
     return true; 
    } 

    public boolean finishedRace() { 
     System.out.printf("Runner %d finished race\n", runnerID); 
     sleepThread(); 
     return true; 
    } 

    private void sleepThread() { 
     try { 
      Thread.sleep(randomGenerator.nextInt(1000)); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(Runner.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    }} 

은 분명히이 겨우 구조와 나는 잔뜩 누락 그래서 쓰기 요구하고 있지 않다 나를위한 전체 프로그램. 여기서 주된 문제는 Runner 클래스의 각 인스턴스가 어떻게 든 다른 인스턴스와 통신하고 모든 Runners가 검사 점에 도달 할 때까지 전체 프로그램을 잠자기 상태로 만드는 것입니다. "포인터"가 도움이 될 것입니다, 감사합니다!

+1

당신은 'CountDownLatch'를 고려 했습니까? – MadProgrammer

+0

들어 본 적이 없으니 확인해 보겠습니다. – OverflowingJava

+1

ForkJoinPool을 사용해 볼 수도 있습니다. invokeAll 메소드를 살펴보십시오. –

답변

1

모든 주자가 체크 포인트를 수행했는지 확인할 수있는 방법이 필요합니다. 이것은 우리가 등 주자의 컬렉션 (배열, ArrayList를을 유지하는 경우 등

public class Runner implements Runnable {  
    private boolean atFirstCheckpoint = false; 
    // ... More checkpoint booleans 
    // ... Rest of the class 

    public boolean hasReachedFirstCheckpoint() { 
     return atFirstCheckpoint; 
    } 
} 

당신의 러너가 checkpoint1 만들어 여부를 추적, checkpoint2를 유지하는 부울 변수의 수를 가지고 수행 할 수) 우리는 모든 주자가 체크 포인트에 도달했는지 확인하는 메소드를 작성할 수 있습니다.

public boolean everyoneHasReachedFirstCheckpoint(Runner[] runners) { 
    for (Runner r : runners) { 
     if (!r.hasReachedFirstCheckpoint()) { 
      return false; 
     } 
     return true; 
    } 
} 

그러면이 확인을 구현하기 위해 arrivedAt1stCheckpoint()를 변경할 수 있습니다. Runner 객체는 배열의 다른 모든 러너가 검사 점에 도달 할 때까지 잠자기 상태가됩니다.

public boolean arrivedAt1stCheckpoint(Runner[] runners) { 
    this.atFirstCheckPoint = true; 
    System.out.printf("Runner %d arrived at 1st checkpoint\n", runnerID); 
    while (!everyoneHasReachedFirstCheckpoint(runners)) { 
     sleepThread(); 
    } 

    return true; 
} 

편집 : 그것은 while 루프의 실행 중에 전체 러너 스레드가 sleepThread() 방법에 따라 시간의 X 금액에 대한 중단 할 것을 염두에두고 가치가있다. 즉, 모든 사람이 체크 포인트를 만들었는지 확인하기 전에 주자가 문자 그대로 X 시간 동안 잠 들어 있음을 의미합니다. 다른 스레드가 머리를 시작할 수있게됩니다.

편집 : 실행자 인터페이스 및/또는 스레드 풀을 사용하여 쉽게 찾을 수있는 러너 (스레드)를 관리 할 수 ​​있습니다.

1

CyclicBarrier 또는 CountDownLatch를 고려해 볼 수 있습니다. 다음은 CyclicBarrier를 사용한 빠른 스 니펫입니다.

는 장벽에 같은 뭔가를 기다릴 필요가 스레드에서 지금이

int BarrierCount = 4; 
CyclicBarrier barrier = new CyclicBarrier(BarrierCount); 

for (int i = 0; i <= BarrierCount; i++) { 
    (new AppThreadsForBarrier(barrier, "name"+i, ...)).start(); 
} 

처럼, 당신은 장벽에 대기하는 스레드에 따라 어떤 장벽을 통과, 당신이 원하는 원하는 카운트 장벽을 설정 아래

class AppThreadsForBarrier extends Thread { 

    // barrier along with other variables you need for your thread 
    public AppThreadsForBarrier(CyclicBarrier barrier, String name, ....) { 
    .. 

    public void run() { 
     try { 
      Thread.sleep(duration); 
      System.out.println(Thread.currentThread().getName() + " is calling await()"); 
      barrier.await(); 
      System.out.println(Thread.currentThread().getName() + " has started running again"); 
      .. 

으로 CyclicBarrier V/s의 해, CountDownLatch를 사용하는 그러나 이것은 당신이 시작하는 그림을 제공해야하는 위치에 대한 약간의 미묘한 차이가 있습니다

을 수행 할 수 있습니다.

관련 문제