2012-02-23 28 views
1

作爲我們大學課程的一部分,我們必須使用Java構建多線程下載服務器。 除了一點之外,一切都運行平穩:我們必須讓服務器在每次下載時顯示每個項目的總下載次數。到目前爲止,我已經得到它的工作,除非兩個客戶同時要求它。代碼如下,如果任何人有任何ides,我會非常感激。我們還必須包含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.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

最根本的問題是,你有兩個線程做一個GET,增量和設置,所以考慮這種情況:

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(); 
} 

您也說過,計數器應計算每個項目的下載數量,但是,您當前的代碼不會這樣做。您當前的計數器將計算所有項目的所有下載量。提示:你所做的一切都是靜態的,並且如果你想爲每個項目分別設置一個計數器,那麼這種方法就不能很好地工作。

+1

+1在生產代碼中,當然我會使用AtomicInteger。另一方面,OP應詢問他們的教授,練習的重點是否準確地在進行簡單解決之前進行同步... – thkala 2012-02-23 18:49:04

+0

@thkala好點,OP應該向他們的教授諮詢瞭解練習的目標(即瞭解同步或原子操作)。 – Kiril 2012-02-23 19:15:26

0

DownloadCounter需要用於遞增的方法。只有getCount和setCount方法沒有安全的方法來增加計數器。

Java有一個AtomicInteger類來處理這種類型的事情。

此外,您只需在DownloadCounter上調用靜態方法,因此不需要創建新實例。

0

使其正確的關鍵在於使get/increment /設置爲原子操作。而不是setCount方法,應該有一個同步incrementCount()方法。

您也可以通過使用AtomicInteger完全避免同步,並在incrementCount()方法中使用其incrementAndGet()方法。

請注意,指令DownloadCounter counter = new DownloadCounter();是完全不必要的。該類應該有一個私有構造函數來防止這種不必要的實例化。