2017-11-28 1 views
1

자바에서 코드 경쟁을 만들고 싶습니다. 기본 계획은 다음과 같습니다.타임 아웃으로 코드 경쟁 구현

  • 각 참가자는 함수 인터페이스를 구현하는 클래스를 제출합니다.
  • 제출 된 각 클래스의 기능을 미리 만들어진 입력 집합에 적용합니다.
  • 각 제출물의 등급은 올바른 출력 개수입니다.

이제 타임 아웃을 추가하고 싶습니다. 각 클래스는 각 입력에서 최대 1 초 동안 실행되도록 허용됩니다. 한 클래스가 1 초 이상 실행될 경우 해당 입력에서 0을 채점하고 점수를 매겨 야합니다.

나의 초기 아이디어는 각 테스트를 별도의 스레드에서 실행하고 잠시 후에 스레드를 중지하는 것이 었습니다. 그러나 to stop a thread in Java, it is required to change its code. 여기에 코드가 다른 사람들에 의해 제출되고 모든 제출물을 읽음으로써 방해를 허용하는지 확인하고 싶지 않습니다.

어떻게 이러한 경쟁을 구현할 수 있습니까?

+0

별도의 프로세스로 실행하십시오. 그 과정을 끝내라. –

답변

2

스레드는 리소스를 공평하게 공유하지 않을 수 있습니다. 따라서 "온라인 판사"의 벽시계 시간은 특히 두 번째 또는 분 범위에서 설정된 상한을 고려해야합니다.

사람들이 최적화 된 솔루션을 사용하고 있는지 확인하려면 한도를 훨씬 높게 설정하고 합리적인 알고리즘을 사용하는 데이터 세트가있는 테스트 케이스를 몇 개 추가 할 수 있습니다. 경쟁하는 데 10 분이 걸리면 작은 스케줄링 차이가 발생할 확률이 더 정교한 CPU 시간 측정의 필요성을 제거하는 방법으로 평균화됩니다.

스레드 안전성에 관해서는이 경우 스레드를 사용하지 않는 것이 좋습니다. 프로세스를 산란 시키면 온라인 심사 위원이 부담을 덜고 한 참가자가 다른 참가자를 검사/간섭하지 못하도록 막고 (kill 신호로) 명백한 종료 수단을 제공하고 더 나은 벤치 마크 표시를 허용합니다 (Unix 명령 "시간"과 유사). .

스레드 환경에서 문제가 발생하면 프로세스를 사용하여 프로그램을 불안정하게 만들 가능성이 있습니다. 추가 장벽으로 인해 이러한 불안정화로 인해 온라인 판단이 영향을받지 않습니다.

+0

흥미 롭습니다. 따라서 올바르게 이해한다면 각 참가자가 인터페이스를 구현하는 클래스를 작성하는 대신 각 참가자가 전체 프로그램 (stdin에서 읽고 stdout에 쓰는 등)을 작성하고 프로세스의 각 프로그램을 테스트하도록해야합니다. 이 올바른지? –

+0

* 따라서 "온라인 판사"의 벽시계 시간은 의심 될 수 있습니다 *. 정확하게! 실이 있었다! 이 * 코드 - 경쟁 * 웹 사이트 중 하나에서 비슷한 기능을 구현하는 사용자의 요청에 대한 응답으로이 문제를 논의합니다. 기본적으로 유사한 시간 복잡도를 갖는 알고리즘의 실행 시간을 측정하는 것은 의미있는 결과를 산출하지 못합니다. 가능한 유일한 옵션은 점근 시간의 복잡성을 비교하여 제출물을 채점하는 것입니다. – jrook

+1

@ ErelSegal-Halevi 여러분은 여전히 ​​클래스를 작성하게 할 수 있습니다. 클래스가 들어 맞는 프레임 워크 (프로그램 래퍼) 만 제공하면됩니다. 어쨌든, jrook의 의견에 대해 생각해보십시오. CPU에서 다른 일을 스케줄링 할 수는 없으므로 어떤 종류의 타이밍을 원한다면 "잘못된 시간에 실행"하는 것이 충분한 영향을 미치지 않거나 시간을 잰 프로세스의 타임 슬라이스를 훔칠 수있는 다른 것을 보장하지 않는 사용자 정의 된 운영 체제 (실시간 OS)를 보유하고 있어야합니다. –

1

Junit을 사용하고 계십니까? 이것을 시도해 볼 수 있습니다. https://github.com/junit-team/junit4/wiki/timeout-for-tests

+0

흥미 롭습니다. 그러나 인터럽트 가능한 작업이 실행되는 동안 테스트가 시간 초과되면 테스트를 실행하는 스레드가 종료됩니다 (테스트가 무한 루프에있는 경우 테스트를 실행하는 스레드가 실행됩니다) 영원히, 다른 테스트가 실행하는 동안). " –

+0

Ooop, 나는 그것을 놓쳤다 - 미안. 아마도 이런 것이 도움이 될까요? 내가 아이디어가 없다는 것을 인정하지만 https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html 행운을 빈다. –

1

그래서 이것을 구현할 수있는 한 가지 방법은 1 명의 경쟁자에게 2 개의 개별 스레드를 사용하는 것입니다. 기능을 실행하는 ThreadTimer과 ThreadHelper

public class ThreadTimer extends Thread { 

    public ThreadTimer() { 

    } 

    @Override 
    public void run() { 

     try { 

      Thread.sleep(1000); 

     } catch (InterruptedException ex) { 
      Logger.getLogger(ThreadTimer.class.getName()).log(Level.SEVERE, null, ex); 
     } 

    } 

} 

그리고 ThreadHelper

public class ThreadHelper extends Thread { 

    Calculator c; 

    public ThreadHelper(Calculator c) { 
     this.c = c; 
    } 

    public Calculator getC() { 
     return c; 
    } 

    public void setC(Calculator c) { 
     this.c = c; 
    } 

    @Override 
    public void run() { 

     long startTime = System.nanoTime(); 
     long plus = c.add();   
     long endTime = System.nanoTime(); 


     long duration = (endTime - startTime); 
     long seconds = duration/1000000000; 

     System.out.println("Add Time: " + seconds); 

    } 

} 

당신이 내 코드에서 계산기를 호출하고 만들어 귀하의 인터페이스를 제공합니다.

이것은 add가 소요 시간을 출력하고 출력하는 시간을 계산합니다. 나는 계산은 훨씬 더 복잡 확신하지만, 질문에 대한 잠재적 인 대답은 시작 클래스에 와서 : ThreadTimer 전에 완료하면 당신은 더 이상 stop() 방법을 사용할 수 없기 때문에, 당신은 예외를 던질 수

public class Competition { 

    public static void main(String[] args) throws InterruptedException, Exception { 
     Calculator jim = new JimSmithsCalculator(); 
     Calculator john = new JohnDoesCalculator(); 

     ThreadHelper jimsThread = new ThreadHelper(jim); 
     ThreadTimer time1 = new ThreadTimer(); 
     ThreadHelper JohnsThread = new ThreadHelper(john); 
     ThreadTimer time2 = new ThreadTimer(); 

     time1.start(); 
     jimsThread.start(); 

     //This will run a loop ensuring both of the above threads are terminated... 
     checkSeconds(time1, jimsThread);//This also does the time check 

     //...Before moving on to these threads. 
     time2.start(); 
     JohnsThread.start(); 


     checkSeconds(time2, JohnsThread); 


    } 

    public static void checkSeconds(ThreadTimer time, ThreadHelper t) throws Exception { 

     while (t.isAlive()) { 
      if (time.getState() == Thread.State.TERMINATED) { 

       throw new Exception(t.getName() + " >> " + t.getClass() + " Failed!!!"); 
      } 

     } 

    } 

} 

ThreadHelper는 않습니다.

이렇게하면 예외가 출력되고 프로그램이 계속됩니다. 그런 다음 경쟁 업체 스레드가 예외로 인해 실패했음을 알 수 있습니다.

public static void checkSeconds(ThreadTimer time, ThreadHelper t) throws Exception { 

    while (t.isAlive()) { 
     if (time.getState() == Thread.State.TERMINATED) { 

      throw new Exception(t.getName() + " >> " + t.getClass() + " Failed!!!"); 
     } 

    } 

} 

당신이 원하는 것처럼이 정확하게 작동한다면 나도 몰라 :

이 임의의 코드를 귀하의 질문에 대한 내 대답의 모든 주요 점은이 방법이다.

적어도이 아이디어가 나올 수 있기를 바랍니다.