2 Stimmen

Gleichzeitige Download-Zähler in Java

Als Teil unserer Kursarbeit an der Universität müssen wir einen Multi-Threading-Download-Server in Java erstellen. Alles läuft reibungslos, bis auf eine Kleinigkeit: Der Server muss die Gesamtzahl der Downloads für jedes Element anzeigen, wenn es heruntergeladen wird. Bis jetzt habe ich es geschafft, dass es funktioniert, wenn nicht beide Clients es gleichzeitig anfordern. Der Code ist unten, wenn jemand irgendwelche Ideen hat, wäre ich sehr dankbar. Auch müssen wir thread.sleep Teil enthalten und müssen den Zähler in dieser verworrenen Weise zu erhöhen.

//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;

Der 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;
    }
}

4voto

Kiril Punkte 38504

Das grundsätzliche Problem besteht darin, dass Sie zwei Threads haben, die ein Get, Inkrement und Set ausführen, also betrachten Sie diese Situation:

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!!!

Die Lösung besteht darin, eine Inkrement-Methode zu implementieren, die die Zählung auf eine thread-sichere Weise erhöht:

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

Sie können auch eine AtomicInteger und vermeiden Sie die Sperrung:

AtomicInteger count = new AtomicInteger(0);

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

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

Sie haben auch angegeben, dass der Zähler die Anzahl der Downloads für jedes Element zählen soll, aber Ihr aktueller Code tut das nicht. Ihr aktueller Zähler zählt ALLE Downloads für ALLE Artikel. Hinweis: Sie machen alles in DownloadCounter statisch und das funktioniert nicht gut, wenn Sie für jeden Artikel einen eigenen Zähler haben wollen.

0voto

Michael Krussel Punkte 2526

DownloadCounter benötigt eine Methode zum Inkrementieren. Es gibt keinen sicheren Weg, den Zähler mit nur einer getCount- und setCount-Methode zu inkrementieren.

Java verfügt über eine Klasse AtomicInteger, die genau für diese Art von Aufgaben geeignet ist.

Außerdem rufen Sie nur statische Methoden auf DownloadCounter auf, so dass es nicht notwendig ist, eine neue Instanz zu erstellen.

0voto

JB Nizet Punkte 654813

Der Schlüssel zum Erfolg liegt darin, dass get/increment/set zu einer atomaren Operation wird. Anstatt die setCount Methode, sollte es eine synchronisierte incrementCount() Methode.

Sie könnten die Synchronisierung auch vollständig vermeiden, indem Sie eine AtomicInteger verwenden und deren incrementAndGet() Methode innerhalb der incrementCount() méthode.

Beachten Sie, dass die Anweisung DownloadCounter counter = new DownloadCounter(); ist völlig unnötig. Die Klasse sollte einen privaten Konstruktor haben, um solche unnötigen Instanziierungen zu verhindern.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X