2016-04-02 12 views
2

リアルタイムインベントリを提供するアプリケーションには、2つのWebサービスが実行されています。私は、これらの2つのインターフェイスから在庫を読み取り、総在庫を計算するJavaマルチスレッドプログラムを書く必要があります。マルチスレッドを使用して2つのWebサービスを集計するにはどうすればよいですか?

事前条件:両方のスレッドを遅滞なく開始する必要があります。

以下のコードを使用してこの問題に近づいてみました。これが正しいかどうかを確認してお知らせください。利用可能な別のアプローチもあります。

package com.app.thread; 

public class InventoryThread { 

    public static void main(String a[]) throws InterruptedException { 

     Inventory inv = new Inventory(); 
     InventoryInterface1 i1 = new InventoryInterface1(inv); 
     InventoryInterface2 i2 = new InventoryInterface2(inv); 

     Thread t1 = new Thread(i1, "T1"); 
     Thread t2 = new Thread(i2, "T2"); 

     t1.start(); 
     t2.start(); 

     t1.join(); 
     t2.join(); 

     System.out.println(inv.getInventory()); 
    } 
} 

class Inventory { 

    private long inventory; 

    public long getInventory() { 
     return inventory; 
    } 

    public void setInventory(long inventory) { 
     this.inventory = inventory; 
    } 
} 

class InventoryInterface1 implements Runnable { 

    private Inventory inv; 

    public InventoryInterface1(Inventory inv) { 
     this.inv = inv; 
    } 

    public void run() { 
     System.out.println(Thread.currentThread().getName() + " running"); 
     synchronized (inv) {    
      System.out.println(Thread.currentThread().getName() + " updates inventory"); 
      inv.setInventory(inv.getInventory() + 100);   
     } 
    } 
} 

class InventoryInterface2 implements Runnable { 
    private Inventory inv; 

    public InventoryInterface2(Inventory inv) { 
     this.inv = inv; 
    } 

    public void run() { 
     System.out.println(Thread.currentThread().getName() + " running"); 
     synchronized (inv) { 
      try { 
       System.out.println(Thread.currentThread().getName() + " waiting.."); 
       while(inv.getInventory() <= 0){ 
        inv.wait(); 
       }    
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      System.out.println(Thread.currentThread().getName() + " updates inventory"); 
      inv.setInventory(inv.getInventory() + 200); 
      System.out.println(Thread.currentThread().getName() + " notifies"); 
      inv.notifyAll(); 
     } 
    } 
} 
+0

InventoryInterface1InventoryInterface2を修正しています。あなたの例で間違っている点がいくつかあります。答えのようなチュートリアルが必要です。 –

+0

@loannis私はJavaの並行性を学んでおり、解決するように求められた問題の専門家の入力を得たいと思っていました。ありがとう! – Vel

答えて

1

変更Inventory.inventory。あなたは文句を言わないInventoryInterface1 & InventoryInterface2

class Inventory { 

    private AtomicLong inventory = new AtomicLong(); 

    public long getInventory() { 
     return inventory.longValue(); 
    } 

    public void incrementInventory(long inventory) { 
     inventory.addAndGet(inventory); 
    } 
} 

問題にInventoryインスタンス上のsyncronizationを必要とするその方法は、それが読み込み、Javalongにアトミックである必要はありません書き込みです。 AtomicLongのaddAndGetはアトミックな操作です。ここで

は、私はあなたが最初の同時実行のチュートリアルを読むことをお勧めしたい

class InventoryInterface1 implements Runnable { 

    private Inventory inv; 

    public InventoryInterface1(Inventory inv) { 
     this.inv = inv; 
    } 

    public void run() { 
     System.out.println(Thread.currentThread().getName() + " running"); 
     System.out.println(Thread.currentThread().getName() + " updates inventory"); 
     inv.incrementInventory(100);   

    } 
} 



    class InventoryInterface2 implements Runnable { 

    private Inventory inv; 

    public InventoryInterface2(Inventory inv) { 
     this.inv = inv; 
    } 

    public void run() { 
     System.out.println(Thread.currentThread().getName() + " running"); 
     System.out.println(Thread.currentThread().getName() + " updates inventory"); 
     inv.incrementInventory(200); 
    } 
} 
+0

これは役に立ちます。 Nullポインタの例外を避けるために、AtomicLongオブジェクトをInventoryクラスで作成する必要があります。ありがとう。 – Vel

+1

投稿を更新しました。ありがとう。 – Sanj

0

一つだけが一度にアクティブにできるので、あなたのRunnableスレッドの両方が彼らの全体の実行のために同期されている場合は、マルチスレッドのパフォーマンスの改善が見られるかどうかはわかりません。しかし、一般的なアプローチは正しく見えますが、実際に共有メモリにアクセスしているときに同期を制限しようとします。

更新

あなたも、スレッドの一つが、同期ロックを保持してもロックが解放されるまで実行できない他のスレッドを待っているデッドロック状態を有していても良いように見えます。あなたはinv.wait()を呼び出す前にロックを解除することができますが、実際にはinvへのアクセスの周りでより精細な同期を使用するだけです。

どのスレッドが最初に実行されるかは実際気になりますか?マルチスレッドを使用したくない場合は、wait()InventoryInterface2から削除する可能性があります。 AtomicLong

class InventoryInterface2 implements Runnable { 
    private Inventory inv; 

    public InventoryInterface2(Inventory inv) { 
     this.inv = inv; 
    } 

    public void run() { 
     System.out.println(Thread.currentThread().getName() + " running"); 
     synchronized (inv) { 
     System.out.println(Thread.currentThread().getName() + " updates inventory"); 
     inv.setInventory(inv.getInventory() + 200); 
     System.out.println(Thread.currentThread().getName() + " notifies"); 
     inv.notifyAll(); 
    } 

} 
+0

スレッド間通信のためにwait()を追加しました。デッドロックは発生しません。私はあなたの変更を実行し、それも動作します。ありがとう。 – Vel