Java中的并发下载计数器

时间:2012-02-23 18:29:49

标签: java multithreading concurrency counter

作为我们大学课程的一部分,我们必须使用Java制作多线程下载服务器。 除了一点之外,一切都在顺利运行:我们必须让服务器在每次下载时显示每个项目的下载总数。到目前为止,我已经让它工作,除非两个客户同时请求它。代码如下,如果任何人有任何想法,我将非常感激。此外,我们必须包含thread.sleep部分,并且必须以复杂的方式递增计数器。

//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 个答案:

答案 0 :(得分:3)

根本问题是你有两个线程正在进行get,increment和set,所以请考虑这种情况:

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 :(得分:0)

DownloadCounter需要一种递增方法。仅使用getCount和setCount方法来增加计数器没有安全的方法。

Java有一个类AtomicInteger来处理这类事情。

此外,您只在DownloadCounter上调用静态方法,因此无需创建新实例。

答案 2 :(得分:0)

使其正确的关键是使get / increment / set成为原子操作。应该有一个同步的setCount方法,而不是incrementCount()方法。

您还可以使用AtomicInteger完全避免同步,并在incrementAndGet()方法中使用其incrementCount()方法。

请注意,指令DownloadCounter counter = new DownloadCounter();完全没必要。该类应该有一个私有构造函数来防止这种不必要的实例化。