2017-04-01 25 views
0

Javaマルチスレッドプログラミングの初心者です。私はDinerと呼ばれる実行可能クラスを持っていて、プログラム内のさまざまな変数の状態に基づいて、Dinerクラスの異なるメソッドを並列実行したいというユースケースがあります。 これを行う1つの方法は、以下に示すように実行したい異なるコードブロックに対応する複数のif条件を含む単一のrun()メソッドを持つことです。スレッド内で実行可能な複数のメソッドを持つJavaクラス

public class Diner implements Runnable { 
     Order order; 
     int arrivalTime; 



     public void run() { 
      if(!isSeated){ 
       //do something to get a seat 
      } 
      if(!notEatenYet){ 
       //place order 
      } 
      if(!orderHasArrived){ 
       //start eating 
      } 
      if(finishedEating){ 
       //pay bill and leave 
      } 
     } 
    } 

しかし、これを行うにはもっとエレガントな方法がありますか?並列化できるメソッドを1つしか持たないのと同様に、クラス内で並列化できるメソッドが異なります(オーバーロードrun()?)。

私はAkka Actorsを使ってこのようなことができると信じていますが、私はネイティブソリューションを探しています。

+0

あなたはこれを参考にしましたか?http://crunchify.com/how-to-run-multiple-threads-concurrently-in-java-executorservice-approach/ –

+0

@RajithPemabanduあなたが参照した記事は、単にExectutorService '複数のスレッドを起動して管理するのではなく、それぞれに個別の' Thread'オブジェクトを作成することです。作成されるすべてのスレッドは、並列に、すなわちホストにpingを実行する必要があるタスクを1つしか持たない。それは私の質問が指していることではありません。 –

+0

あなたは本当にクラスのメソッドを並行して実行したいですか?私はほとんど座っている食べて、食べ、そして請求書を支払う食堂を想像することはほとんどありません:この行動は厳密に逐次的です。 –

答えて

2

あなたがマルチスレッドに慣れていない場合は、徐々にそれを緩和することを検討してください。 1つのワーカースレッドから開始し、すべてのダイナーのタスクをこの1つのスレッドに投稿します。これにより、スレッドへのサブミットタスクはブロックされませんが、同じダイナーに同時にアクセスする複数のスレッド(同期、デッドロックの危険性、競合状態のリスクなど)の複雑さの多くを排除します。

ここで単一スレッドのスケジュールされたエグゼキュータを使用する例です。 2,4,6秒でイベントが発生するようにスケジュールしていますが、呼び出しスレッドは各イベントの待機をブロックしません(最後に人工ブロックを追加してカウントダウンラッチを追加するので、executorをきれいにシャットダウンできます)

public class Diner { 

    public void findSeat() { 
     System.out.println("findSeat"); 
    } 
    public void placeOrder() { 
     System.out.println("placeOrder"); 
    } 

    public static void main(String[] args) throws InterruptedException { 
     final ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); 
     final CountDownLatch done = new CountDownLatch(1); 

     final Diner diner = new Diner(); 

     exec.schedule(new Runnable() { 
      public void run() { 
       diner.findSeat(); 
      } 
     }, 2, TimeUnit.SECONDS); 

     exec.schedule(new Runnable() { 
      public void run() { 
       diner.placeOrder(); 
      } 
     }, 4, TimeUnit.SECONDS); 


     exec.schedule(new Runnable() { 
      public void run() { 
       done.countDown(); 
      } 
     }, 6, TimeUnit.SECONDS); 

     done.await(); 
     exec.shutdown(); 
     System.out.println("done"); 
    } 
} 

また、ダイナーがRunnableを実装する必要はありません。必要に応じて、タスクごとに一時ファイル を作成してください。

追加の同時実行性が必要な場合は、2番目、3番目のエグゼキュータ・サービスを追加します。 のタスクが「ステートレス」(データベースクエリなど)の場合は、複数のスレッドで新しい エグゼキュータサービスを追加して、並列性を向上させることができます。ダイナーを直接変更するのではなく、Diner エグゼキュータにタスクをスケジューリングすることによって、DBスレッドがダイナーを更新するときに を確実に確認してください。

これはAkka風のスタイルを提供しますが、ネイティブJavaユーティリティを使用するだけです。

1
public class SOCLass { 

    public void method1(){ 
     System.out.println("method1"); 
    } 

    public void method2(){ 
     System.out.println("method1"); 
    } 

    public static void main(String[] args){ 
     SOCLass clazz = new SOCLass(); 

     Runnable task1 =() -> { clazz.method1();};  
     Thread t1 = new Thread(task1); 
     t1.start(); 

     Runnable task2 =() -> { clazz.method2();};  
     Thread t2 = new Thread(task1); 
     t2.start(); 

     try { 
      t1.join(); 
      t2.join(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 

EDIT

私はあなたのケースのために、このアプローチは、より良い仕事だと思います。ブール値を評価した後、起動タスクメソッドでスレッドを起動できます。ちょうど1つのダイナーインスタンス

はちょうどあなたが私の意見では、彼らに

0

を制御することができる場所でスレッドを維持する、あなたのケースのために、簡単な継承は良いオプションをすることができます。

あなたがメインで、いくつかの他のサブクラス

//、いくつかのサブクラスだから1つのダイナー抽象クラスといくつかのサブのクラスが存在することになるDiner

を継承

public abstract class Diner implements Runable{ 
    public Order order; 
    public int arrivalTime; 
} 

public class NotSeatedDiner extends Diner { 
    public void run() { 
     // do something to find a seat 
    } 
} 

を持つことができます機能を持つことができます

List diners = new ArrayList<Diner>(); 

//maybe some factory producing different diners 

diners.add(fac.getDiner("not seated")); 

for(Diner diner : diners){ 
    diner.run(); 
} 
関連する問題