2016-08-17 4 views
1

私はシミュレータを作成していますが、簡単にするために、これは「ゲーム」です。したがって、render()とupdate()関数があります。私は夏にラムダ式を練習しようとしていましたが、別のラムダ式のラムダ式をやっていくことで私の頭を包み込むことができないようです。私はおそらく、この間違ったことを言ったが、私は何をしようとしていることをレンダリングする二つのスレッド、1 そのループを開始しており、別のそのループを更新しています。私はここまでを取得することができます:Java 8可能なダブルラムダ式

void render() { 
    //draw entities, etc. 
} 
void update() { 
    //update player/enemies, etc. 
} 

public GameFrame() { 
    /* init stuff */ 
    Thread updateThread = new Thread(this::update); 
    Thread renderThread = new Thread(this::render); 
} 

これは、これが唯一のアップデートを実行し、一度描くので、私が欲しいものではありません。したがって、これはちょうど2つのスレッド、1 は一度をレンダリングし、1 は一度を更新(ありますルーピングなし)。

public void loop(Supplier< /*?*/ > arg) { 
    long startTime; 
    while(running) { 
     startTime = System.currentTimeMillis(); 
     supplier.get(arg) // <- not sure about this either 
     try { 
      long sleepTime = 1000/FPS - (System.currentTimeMillis() - startTime); 
      if(sleepTime > 0) 
       Thread.sleep(sleepTime); 
     } catch(InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

私はこのような関数を呼び出しますか?

loop(this::update); 

私は、このように私が試した、これはループに供給される機能を引き起こすと考えている:

Thread updateThread = new Thread(this::loop(this::update)); 

、さらにはこのような何か:

new Thread(() -> loop(this::update)).start(); 

を私はちょうど私がレンダリングすることができます知っていますfunction while whileループと私の更新関数は、それぞれの部分に 'void loop(Supplier arg)'コードをコピーするだけでループしますが、私はこの方法をとにかくできるかどうかを見たいと思っていました。

私は正確な答えは必要ありませんが、私は私が間違って考えていることについて/私が間違って考えているものにいくつかの指針をしたいです。私はoracle上のラムダ式を読み上げることで多くの進歩を遂げることができませんでした。

+3

あなたの最後のアイデアはOKですが、loop()メソッドは、引数を取らず何も返さない関数を実行したいのでRunnableを引数として受け取ります。したがって、各実行時にその実行可能ファイルに対してrun()を呼び出す必要があります。 –

+4

まず、タイマーを使用する代わりに "スリープループ"を考えているのはなぜですか? – RealSkeptic

+2

ベアメタルスレッドを使用する代わりに、ExecutorServicesを使用してジョブをジョブに投入し続けることもできます。それはlambdaの助けにはなりませんが、マルチスレッド・エグゼキュータ・サービスを "現時点でdo-it-in-thread-thread"エグゼキュータに置き換えることができるため、テストが非常に簡単になります。 – GhostCat

答えて

1

ThreadコンストラクタにはRunnableが必要です。これは繰り返し実行するものです。したがってloopのパラメータタイプとしてSupplierは必要ありませんが、Runnableです。

public void loop(Runnable arg) { 
    long startTime; 
    while(running) { 
     startTime = System.currentTimeMillis(); 
     arg.run(); 
     try { 
      long sleepTime = 1000/FPS - (System.currentTimeMillis() - startTime); 
      if(sleepTime > 0) 
       Thread.sleep(sleepTime); 
     } catch(InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

メソッド参照でパラメータを指定することはできません。これは無効な構文です:

this::loop(this::update) 

あなたがスレッドを実行する文は次のとおりです。

loop(this::update); 

ので、あなたがThreadコンストラクタのパラメータとして体としてこの文でラムダ式を使用する必要があります。

Thread updateThread = new Thread(() -> loop(this::update)); 

ScheduledExecutorServiceは、ここで実装している種類のスケジューリングを提供します。

+0

'this :: loop(this :: update)'?なぜ関数にパラメータがあるなら、 '() - > doFoo(arg)'のように参照する必要があることに気付きました。これはなぜですか? –

+0

a)メソッドリファレンスが動作するためのターゲット型が必要です( 'this :: loop'のためには存在しません)。b)ターゲット型を持っていても、javaはあなたはそれを異なって実装する必要があります。 – fabian

関連する問題