2012-02-23 6 views
1

大学の授業の一環として、Javaでマルチスレッドダウンロードサーバーを作成する必要があります。 すべてが1つのビットからスムーズに実行されています。ダウンロードするたびに、各アイテムの合計ダウンロード数をサーバーに表示させる必要があります。これまで私は、両方のクライアントが同時に要求しない限り、動作させるようにしました。コードは以下の通りです。誰かが仲間を持っているなら、私はとても感謝しています。また、thread.sleep部分を含める必要があり、その畳み込まれた方法でカウンタをインクリメントする必要があります。Javaでの同時ダウンロードカウンタ

//Snipper from Protocol.java 

if (theInput.equals("1")) { 

      theOutput = "The program displays a message... Another? Y or N"; 


      DownloadCounter counter = new DownloadCounter(); 

      count = DownloadCounter.getcount();//count is a var in Protocol.java it is      static 

      int tmp = count; 
      try { 
       Thread.sleep(5000); 
      } catch (InterruptedException ex) { 
       System.out.println("sleep interrupted"); 
      } 
      count = tmp + 1; 

      DownloadCounter.setcount(count); 

      System.out.println("Download Total " + count); 


      state = ANOTHER; 

DownloadCounter:インクリメントするための方法を必要とDownloadCounter

//DownloadCounter.java 
public class DownloadCounter { 

    private static int count; 

    public static synchronized int getcount(){ 
     return count; 
    } 

    public static synchronized void setcount(int num){ 
     DownloadCounter.count = num; 
    } 
} 

答えて

3

根本的な問題は、あなたが得る、インクリメントとセットをやって二つのスレッドを持っているということですので、このような状況を考慮してください。

Thread 1: set(5) // now count is 5 
Thread 1: get() // Thread 1 gets 5 
Thread 2: get() // Thread 2 gets 5 
Thread 2: increments its local copy of count to 6 
Thread 1: increments its local copy of count to 6 
Thread 2: set(6) // now the count is 6 
Thread 1: set(6) // the count is still 6, but it should be 7!!! 

ソリューションは、スレッドセーフな方法でカウントをインクリメントし、インクリメント方法を実装することです:

public synchronized void increment() 
{ 
    count++; 
} 

ます。またAtomicIntegerを使用してロックを回避することができます。

AtomicInteger count = new AtomicInteger(0); 

public int getCount() 
{ 
    return count.get(); 
} 

public void increment() 
{ 
    count.incrementAndGet(); 
} 

また、カウンターは各アイテムのダウンロード数をカウントする必要がありますが、現在のコードではそれが行われません。現在のカウンタは、すべてのアイテムのすべてのダウンロードをカウントします。ヒント:DownloadCounterのすべてを静的にしていますが、各アイテムごとに別々のカウンタを使用する場合は、うまく機能しません。

+1

+1生産コードではもちろん、AtomicIntegerを使用します。一方、OPは、簡単な解決策をとる前に、演習のポイントが自分自身で同期を行うかどうかを教授に尋ねるべきです... – thkala

+0

@thkala良い点は、OPは間違いなく教授と相談してください演習の目標を理解する(つまり、同期や原子操作について学ぶ)。 – Kiril

0

。 getCountメソッドとsetCountメソッドだけでカウンタをインクリメントする安全な方法はありません。

Javaには、このタイプのものだけを扱うAtomicIntegerクラスがあります。

また、DownloadCounterで静的メソッドを呼び出すだけなので、新しいインスタンスを作成する必要はありません。

0

正確にするための鍵は、アトミック操作のget/increment/setを正確に行うことです。 setCountメソッドの代わりに、同期されたincrementCount()メソッドが必要です。

また、AtomicIntegerを使用して同期を完全に回避し、incrementCount()メソッド内でincrementAndGet()メソッドを使用することもできます。

命令DownloadCounter counter = new DownloadCounter();は完全に不要であることに注意してください。このような不要なインスタンス化を防ぐために、クラスには専用のコンストラクタが必要です。

関連する問題