2017-11-28 15 views
1

Javaでコード競争を作りたいと思います。基本計画は、タイムアウトのあるコード競合の実装

  • です。各競技者は、関数インタフェースを実装するクラスを送信します。
  • 私は、提出された各クラスの機能を、あらかじめ作られた入力のセットに適用します。
  • 各投稿のグレードは、正しい出力数です。

ここで、タイムアウトを追加します。各クラスは、各入力で最大1秒間実行できます。あるクラスが1秒以上実行されている場合は、その入力に対してクラスを停止して0にする必要があります。

私の最初のアイデアは、別のスレッドで各テストを実行し、1秒後にスレッドを停止することでした。しかし、to stop a thread in Java, it is required to change its code。ここでは、コードは他の人によって提出されており、すべての投稿を読んで割り込みが許可されていることを確認したくありません。

このような競技はどのように実装できますか?

+0

別のプロセスで実行します。プロセスを終了します。 –

答えて

2

スレッドは公平にリソースを共有することは保証されていません。したがって、 "オンラインジャッジ"での壁時計の時間は、特に上限が2番目または3番目の範囲に設定されていることが疑わしい。

人々が最適化されたソリューションを使用しているかどうかを判断するには、上限をもっと高く設定し、妥当なアルゴリズムを使用していることを確認したデータセットを含むテストケースを追加します。競合する時間が10分の場合、小さなスケジューリングの違いの確率は、より洗練されたCPU時間測定の必要性を無くす方法で平均しています。

スレッドセーフについては、この場合はスレッドを使用しない方がいいでしょう。プロセスの起動は、オンラインジャッジをオフロードし、ある競技者が別のプレイヤーを検査/干渉しないようにし、(killシグナルによって)明白な終了手段を提供し、より良いベンチマークのマーキングを可能にする(Unixコマンド "time"に類似) 。

スレッド環境で何かがうまくいかない場合、プロセスを使用してプログラムを不安定にする可能性があります。このような不安定化がプロセスを使用してオンライン裁判官に影響を及ぼすことを防ぎます。

+0

だから私が正しく理解するならば、各参加者にインターフェースを実装するクラスを書くのではなく、各参加者にプログラム全体(stdinから読み込み、stdoutに書き込む)を書き込ませ、プロセス内の各プログラムをテストさせるべきです。これは正しいです? –

+0

*したがって、「オンラインジャッジ」の壁時計の時刻は疑わしいと思われます*。まったく!スレッドがありました!これらの*コード競争*ウェブサイトの1つで、ユーザーからの同様の機能の実行要求に応じてこれを議論しています。基本的には、同様の時間複雑度を持つアルゴリズムの実行時間を測定しても意味のある結果は得られません。実行可能な唯一の選択肢は、漸近的な時間の複雑さを比較することによって提出を採点するようです。 – jrook

+1

@ ErelSegal-Haleviあなたはまだクラスを書くことができます。クラスを収める必要があるフレームワーク(プログラムラッパー)を提供するだけです。いずれにせよ、ジョークのコメントについて考える。あなたは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つのスレッドを使用することです。あなたは、私は私のコードで電卓を呼び出しています作成したインターフェース

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); 

    } 

} 

関数を実行ThreadTimerとA 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。

これは、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!!!"); 
     } 

    } 

} 

あなたがそれを望むよう、これは正確に動作するかどうかはわからない:

このランダムなコードやあなたの質問に私の答えのすべての主要なポイントは、この方法です。

私はこれが少なくともアイデアを発することを願っています。

関連する問題