2012-02-23 73 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();是完全不必要的。该类应该有一个私有构造函数来防止这种不必要的实例化。