Wie man ein Thread-Limit in Java erstellt

8

Nehmen wir an, ich habe 1000 Dateien zu lesen, und wegen einiger Einschränkungen möchte ich maximal 5 Dateien parallel lesen. Und sobald einer von ihnen fertig ist, möchte ich einen neuen starten.

Ich habe eine Hauptfunktion, die die Liste der Dateien haben, und ich versuche, einen Zähler zu ändern, wenn ein Thread beendet ist. aber es funktioniert nicht!

Irgendwelche Vorschläge?

Das Folgende ist die Hauptfunktionsschleife

%Vor%     
Afshin Moazami 28.12.2011, 03:07
quelle

4 Antworten

19

Solche Fäden zu erzeugen, ist nicht der richtige Weg. Verwenden Sie ExecutorService und geben Sie an, dass der Pool 5 sein soll. Legen Sie alle Dateien in eine BlockingQueue oder eine andere threadsichere Sammlung, und alle ausführbaren Dateien können nur poll() nach Belieben.

%Vor%     
Kylar 28.12.2011, 03:12
quelle
3

Der Ansatz in Kylars Antwort ist der richtige. Verwenden Sie die von den Java-Klassenbibliotheken bereitgestellten Executor-Klassen, anstatt das Thread-Pooling selbst von Grund auf neu zu implementieren (schlecht).

Aber ich dachte, es könnte nützlich sein, den Code in Ihrer Frage zu diskutieren und warum es nicht funktioniert. (Ich habe einige der Teile, die du weggelassen hast, so gut wie möglich ausgefüllt ...)

%Vor%

OK, was ist daran falsch? Warum funktioniert es nicht?

Nun, das erste Problem ist, dass Sie in main counter lesen und schreiben, ohne eine Synchronisation durchzuführen. Ich gehe davon aus, dass es auch von den Worker-Threads aktualisiert wird - ansonsten macht der Code keinen Sinn. Das bedeutet, dass die Wahrscheinlichkeit besteht, dass die Hauptthreads das Ergebnis der von den untergeordneten Threads vorgenommenen Aktualisierungen nicht sehen. Mit anderen Worten, while (counter > 5); könnte eine Endlosschleife sein. (Tatsächlich ist das ziemlich wahrscheinlich. Der JIT-Compiler kann Code erzeugen, in dem counter > 5 einfach den Wert von counter , der in einem Register nach der vorherigen counter++; -Anweisung übrig geblieben ist, testet.

Das zweite Problem ist, dass Ihre while (counter > 5); -Schleife eine unglaubliche Verschwendung von Ressourcen darstellt. Sie sagen der JVM, dass sie eine Variable abfragen soll ... und sie wird dies MILLIARDEN Mal pro Sekunde tun ... einen Prozessor (Kern) ausführen. Du solltest das nicht tun. Wenn Sie solche Dinge mit Low-Level-Primitiven implementieren möchten, sollten Sie die Methoden Object.wait() und Object.notify() von Java verwenden; z.B. Der Haupt-Thread wartet und jeder Worker-Thread benachrichtigt.

    
Stephen C 28.12.2011 04:09
quelle
2

Sie können einen ExecutorService als Thread-Pool UND eine Warteschlange verwenden.

%Vor%     
Peter Lawrey 28.12.2011 11:45
quelle
0

Welche Methode Sie auch verwenden, um einen neuen Thread zu erstellen, einen globalen Zähler zu erhöhen, eine bedingte Anweisung um die Thread-Erstellung hinzuzufügen. Wenn das Limit erreicht wurde, dann erstellen Sie keinen neuen Thread, sondern schieben Sie die Dateien in eine Warteschlange (eine Liste?) und dann können Sie eine weitere bedingte Anweisung hinzufügen, nachdem ein Thread erstellt wurde, wenn es Elemente in der Warteschlange gibt, um diese Elemente zuerst zu verarbeiten.

    
Ozzy 28.12.2011 03:11
quelle

Tags und Links