2011-12-20 9 views
3

Javaで異なる関数のクロススレッドを呼び出す方法を知りたいと思います。今、私はそれをやっている方法はとてもJavaでのクロススレッド関数呼び出し

public volatile boolean invokeMyFunction = false; 

public void run() { 
    while(true) { 
     if(invokeMyFunction) { 
      MyFunction(); 
      invokeMyFunction = false; 
     } 
    } 
} 

としての私のスレッドの私の実行()関数を記述することであり、私は「そのスレッドの書き込みの外から)関数のMyFunctionを(実行したい場合whateverobject.invokeMyFunction =それはループがそれを拾うので、スレッド内から自分の関数を実行します。これは私のためにはうまくいくが、while(true)ループのためにCPUが100%使用されている。私はループ内でThread.sleep(1000)をたたくだけで問題を解決できますが、これは面倒なようですが、これを実行するより良い方法があると信じることはできません。

+0

複数の関数呼び出しが存在する可能性はありますか? 2番目のスレッドで任意の量の関数を呼び出すことができるソリューションが必要ですか? – Lalaland

+0

理想的には、2番目のスレッドで複数の関数を複数回呼び出すことができるソリューションが好きです。 – Macmee

答えて

4

私はここで、これを達成するための最も簡単かつCPUに優しい方法は、上記のコードは、それ自身のスレッドで実行

public void run() { 
    while(true) { 
     synchronized(foo) { 
      while(!invokeMyFunction) { 
       foo.wait(); 
      } 
     } 
     MyFunction(); 
     invokeMyFunction = false; 
    } 
} 

だと思います。 A)あなたはブールをinvokeMyFunction作り、2つだけブール値は、Javaのすべてに存在するため、その上に同期できないことを

invokeMyFunction = true; 
foo.notifyAll(); 

注:) :別のスレッドが最初のスレッドの実行のMyFunctionを()させるためにこれを行うことができますb)invokeMyFunctionがn回設定されている場合、invokeMyFunctionがfalseに設定されていないときにtrueに設定されている場合、実行回数が少なくなることがあります。 BlockingQueueのを使用して c)は、より簡単かもしれないと、スレッド1は、任意の関数を実行できるようになります。

while(true) { 
    Runnable next = queue.take(); 
    next.run() 
} 

、別のスレッドのようにMyFunctionを実行するためにそれを言うだろう:

queue.put(new Runnable() { 
    void run() { 
     MyFunction(); 
    } 
}); 

は私に簡単に思えます: )また、n個のスレッドがキューを経由して実行されるようにするには、キューで待機するn個のスレッドを生成する必要があります。 http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html

注:

queue.put()ブロックを、それが「フル」であれば、新たなスペースがBlockingQueueの、すなわち、そのブロックで使用可能になるまで、または、スレッドプールを使用する方法を学ぶことができます。キューに制限があるかどうかを確認するために使用しているBlockingQueue実装のインプリメンテーションドキュメントを参照してください。いずれにしても、処理するアイテムを追加していないことを確認してください。長時間処理できない場合があります。

+0

エレガントで簡単に実装するために、私が探していたものを正確に - ありがとう – Macmee

2

スレッドにモニタを配置し、そのモニタで待機することができます。関数を呼び出すときは、関数を実行できる人を誰かから解放するようにモニターに指示します(そして、それを持っている必要があります)。

本来、睡眠経路には何も問題はありません。なぜあなたはそれが乱雑であると思うのか分かりますが、それは愚かな間違いをする可能性が低くなり、サービス間の疎結合を提供します。

(サイドモニタ - スレッドにモニタを置く必要はありませんが、そのオブジェクトを内部モニタではなくモニタとして使用できますが、干渉する可能性のある他の人に自分自身を公開することができますプライベート内部オブジェクトをモニタとして使用するのが最善です。)

1

あなたの計画は私にとっては奇妙です。なぜスレッドを開始しますが、未知の時間が来るまで待ってから実行するように指示しますか?なぜ後でそれを始めるのではないのですか? EDITは削除

EDIT glowcoderすることを明確に追加

- 私の悪い、私は彼がMyFunctionのを複数回呼び出すことができるようにしたいと考えて、彼の質問を誤解しました。その場合は、他の回答で示唆されているようにキューの種類を使用する必要があります。

+0

他の操作には、メインスレッドをブロックしていない方が良いでしょう。たとえば、フィードまたはソケット通信の読み取りを考えてみましょう。 – corsiKa

+0

ブロックする必要はなく、別のスレッドで他の操作を実行することはできます。準備が整うまでは、起動しないでください。 – user949300

+0

ではないかもしれませんが、毎回新しいスレッドを開始するか、スレッドプールまたはexecutorサービスを使用する必要があります。私はそれらが学ぶ貴重なものであるので、私は完全に反対ではありませんが、質問の範囲ではありません。 – corsiKa

2

CPUを掘り起こすという点を除いて、コードにはいくつかの穴があります。

他のスレッドがMyFunctionの実行にかかる時間内にこのスレッドを2回起動させたい場合はどうなりますか?あなたは1つの呼び出しを失うことになります。

改善は次のようになります。

public volatile boolean invokeMyFunction = false; 

public void run() { 
    while(true) { 
     if(invokeMyFunction) { 
      // Moved here. 
      invokeMyFunction = false; 
      MyFunction(); 
     } 
    } 
} 

しかし、これが唯一の競合状態が少なく、不可能ではないになります。

私はhereを提案したように、BlockingQueueを使用する方がよい場合があります。もう一方のスレッドは、このスレッドが読み取ったキューに何かを投稿させます。あなたはまた、CPUをそんなに馬鹿にしないでしょう。