500 Worker Threads, welche Art von Thread-Pool?

7

Ich frage mich, ob dies der beste Weg ist, dies zu tun. Ich habe ungefähr 500 Threads, die auf unbestimmte Zeit laufen, aber Thread.sleep für eine Minute, wenn ich einen Verarbeitungszyklus gemacht habe.

%Vor%

Der Code, der ausgeführt wird, ist wirklich einfach und im Grunde nur das

%Vor%

Ich brauche für jede laufende Aufgabe separate Threads, daher ist das Ändern der Architektur keine Option. Ich habe versucht, meine threadPool Größe gleich zu machen Runtime.getRuntime (). AvailableProcessors (), die versucht, alle 500 Threads auszuführen, aber nur 8 (4xhyperthreading) von ihnen auszuführen. Die anderen Threads würden sich nicht ergeben und lassen andere Threads an der Reihe sein. Ich habe versucht, warten () und benachrichtigen (), aber immer noch kein Glück. Wenn jemand ein einfaches Beispiel oder ein paar Tipps hat, wäre ich dankbar!

Nun, das Design ist wohl fehlerhaft. Die Threads implementieren Genetic-Programming oder GP, eine Art Lernalgorithmus. Jeder Thread analysiert fortgeschrittene Trends macht Vorhersagen. Wenn der Thread jemals abgeschlossen wird, ist das Lernen verloren. Das heißt, ich hatte gehofft, dass sleep () mir erlauben würde, einige der Ressourcen zu teilen, während ein Thread nicht "lernt"

Die tatsächlichen Anforderungen sind also

  

Wie kann ich wartende Aufgaben planen?   Zustand und Lauf alle 2 Minuten, aber   Steuern Sie, wie viele auf einmal ausgeführt werden.

    
Submerged 19.05.2010, 18:24
quelle

11 Antworten

10

Warum nicht ein ScheduledExecutorService verwendet, um Planen Sie jede Aufgabe so, dass sie einmal pro Minute ausgeführt wird , anstatt alle diese Threads für eine volle Minute im Leerlauf zu lassen?

%Vor%

Was meinst du mit "Veränderung der Architektur ist keine Option"? Wenn Sie meinen, dass Sie Ihre Aufgabe überhaupt nicht ändern können (insbesondere müssen die Aufgaben in Schleife statt einmal ausgeführt werden, und der Aufruf von Thread.sleep() kann nicht entfernt werden), dann " Gute Leistung ist keine Option. "entweder.

    
erickson 19.05.2010, 18:59
quelle
13

Wenn Ihre Threads nicht enden, ist dies der Fehler des Codes innerhalb des Threads, nicht der Thread-Pool. Für detailliertere Hilfe müssen Sie den Code, der ausgeführt wird, veröffentlichen.

Warum legst du auch jeden Thread in den Schlaf, wenn es fertig ist? Wäre es nicht besser, es einfach fertig zu stellen?

Außerdem glaube ich, dass Sie den Threadpool missbrauchen, indem Sie eine Anzahl von Threads haben, die der Anzahl der Aufgaben entspricht, die Sie ausführen möchten. Der Punkt eines Thread-Pools besteht darin, die Anzahl der verwendeten Ressourcen zu beschränken. Dieser Ansatz ist nicht besser, als überhaupt keinen Threadpool zu verwenden.

Schließlich müssen Sie keine Instanzen von Thread an Ihre ExecutorService übergeben, nur Instanzen von Runnable . ExecutorService behält seinen eigenen Thread-Pool bei, der endlos läuft und die Arbeit aus einer internen Warteschlange entfernt (die Arbeit ist die Runnable s, die du sendest).

    
danben 19.05.2010 18:28
quelle
3

Ich bin mir nicht sicher, ob Ihr Code semantisch korrekt ist, wie er einen Thread-Pool verwendet. ExecutionService erstellt und verwaltet Threads intern. Ein Client sollte nur eine Instanz von Runnable bereitstellen, deren Methode run () im Kontext eines der zusammengefassten Threads ausgeführt wird. Sie können mein Beispiel überprüfen. Beachten Sie außerdem, dass jeder laufende Thread ~ 10 MB Systemspeicher für den Stack benötigt und unter Linux die Zuordnung von Java-zu-Native-Threads 1: 1 ist.

    
bobah 19.05.2010 18:37
quelle
2

Anstatt einen Schritt in den Schlaf zu setzen, sollten Sie es zurückkehren lassen und ein ThreadPoolexecutor , um die Arbeit auszuführen, die jede Minute in Ihre Arbeitswarteschlange gestellt wird.

    
Eugene Kuleshov 19.05.2010 18:39
quelle
2

Um Ihre Frage zu beantworten, welche Art von Thread-Pool?

Ich habe meine Kommentare gepostet, aber das sollte wirklich Ihr Problem ansprechen. Sie haben eine Berechnung, die 2 Sekunden dauern kann. Sie haben viele Aufgaben (500), die Sie so schnell wie möglich erledigen möchten. Der schnellstmögliche Durchsatz, den Sie erreichen können, wenn kein E / A- oder Netzwerkverkehr vorliegt, ist mit Runtime.getRuntime().availableProcessors() Anzahl der Threads.

Wenn Sie Ihre Anzahl auf 500 Threads erhöhen, wird jeder Task in einem eigenen Thread ausgeführt, aber das Betriebssystem plant einen Thread so oft, dass er einem anderen Thread zugewiesen wird. Das sind 125 Kontextwechsel an jedem beliebigen Punkt. Jeder Kontextwechsel erhöht die Zeit für die Ausführung jeder Aufgabe.

Das große Bild hier ist, dass das Hinzufügen von mehr Threads NICHT gleich dem größeren Durchsatz ist, wenn Sie weit über die Anzahl der Prozessoren hinausgehen.

Bearbeiten: Ein schnelles Update. Du musst hier nicht schlafen. Wenn Sie die 500 Aufgaben mit 8 Prozessoren ausführen, wird jede Aufgabe in den 2 Sekunden abgeschlossen und der Thread, auf dem sie ausgeführt wurde, übernimmt dann die nächste Aufgabe und beendet diese Aufgabe.

    
John Vint 19.05.2010 18:52
quelle
1

8 Threads ist das Maximum, mit dem Ihr System umgehen kann, und Sie verlangsamen sich durch Kontextwechsel.

Sehen Sie sich diesen Artikel Ссылка an. Dort erhalten Sie einen Überblick darüber, wie um es zu tun.

    
Romain Hippeau 19.05.2010 18:50
quelle
1

Das sollte tun, was Sie wollen, aber nicht das, wonach Sie gefragt haben :-) Sie müssen das Thread.sleep()

herausnehmen

ScheduledRunnable.java

%Vor%

Damit wird die Runnables alle 10 SEKUNDEN geplant, um das Verhalten anzuzeigen. Wenn Sie wirklich eine bestimmte Zeit warten müssen, nachdem NACH der Verarbeitung abgeschlossen ist, müssen Sie möglicherweise mit der von Ihnen benötigten Methode .scheduleXXX herumspielen. Ich denke, FixedWait wird es nur alle n Mal unabhängig von der Ausführungszeit ausführen.

    
Jarrod Roberson 19.05.2010 20:34
quelle
0
  

Ich brauche für jede laufende Aufgabe separate Threads, daher ist das Ändern der Architektur keine Option.

Wenn wahr ist (z. B. wenn Sie eine externe blockierende Funktion aufrufen), erstellen Sie separate Threads für sie und starten Sie sie. Sie können keinen Thread-Pool mit einer begrenzten Anzahl von Threads erstellen, da eine blockierende Funktion in einem der Threads verhindert, dass andere runnable-Objekte darin eingefügt werden, und nicht viel mit einem Thread pro Task einen Thread-Pool erstellen / p>

  

Ich habe versucht, meine threadPool-Größe gleich zu Runtime.getRuntime (). availableProcessors () zu machen, die versucht hat, alle 500 Threads auszuführen, aber nur 8 (4xhyperthreading) ausführen lassen.

Wenn Sie die Thread-Objekte, die Sie erstellen, an den Thread-Pool übergeben, sehen sie nur, dass sie Runnable implementieren. Daher wird jedes Runnable zum Abschluss ausgeführt. Jede Schleife, die das Zurückgeben der run() -Methode stoppt, lässt nicht zu, dass die nächste eingereihte Aufgabe ausgeführt wird. zB:

%Vor%

wird ausgedruckt:

%Vor%

zeigt an, dass die ersten Tasks (Threadpoolgröße) bis zum Abschluss ausgeführt werden, bevor die nächsten Tasks geplant werden.

Sie müssen Aufgaben erstellen, die für eine Weile ausgeführt werden und dann andere Aufgaben ausführen lassen. Wie Sie diese strukturieren, hängt davon ab, was Sie erreichen möchten

  • ob alle Tasks gleichzeitig ausgeführt werden sollen, alle eine Minute warten, dann alle gleichzeitig ausgeführt werden oder die Tasks nicht miteinander synchronisiert sind
  • ob Sie wirklich möchten, dass jede Aufgabe in einem 1-Minuten-Intervall ausgeführt wird
  • ob Ihre Aufgaben möglicherweise blockieren oder nicht, und erfordern daher wirklich separate Threads
  • welches Verhalten erwartet wird, wenn eine Aufgabe länger als das erwartete Fenster zum Ausführen von
  • blockiert
  • welches Verhalten erwartet wird, wenn eine Aufgabe länger als die Wiederholungsrate blockiert (Blöcke für mehr als eine Minute)

Abhängig von den Antworten auf diese kann eine Kombination von ScheduledExecutorService, Semaphoren oder Mutexen verwendet werden, um die Aufgaben zu koordinieren. Der einfachste Fall sind nicht blockierende, nicht synchrone Tasks. Verwenden Sie in diesem Fall einen ScheduledExecutorService, um Ihre Runnables einmal pro Minute auszuführen.

    
Pete Kirkham 19.05.2010 19:41
quelle
0

Können Sie Ihr Projekt für die Verwendung eines agentenbasierten Concurrency-Frameworks wie Akka neu schreiben?

    
Igor Artamonov 19.05.2010 20:02
quelle
-1

Sie können sicherlich eine Verbesserung des Durchsatzes feststellen, indem Sie die Anzahl der Threads auf das reduzieren, was das System realistisch handhaben kann. Sind Sie offen dafür, das Design des Threads etwas zu verändern? Es entlastet den Scheduler, um die Schlafenden in eine Warteschlange zu stellen, anstatt hunderte schlafende Threads zu haben.

%Vor%

Dies bewahrt Ihre Kernsemantik von 'Job wiederholt auf unbestimmte Zeit, aber wartet mindestens eine Minute zwischen den Ausführungen', aber jetzt können Sie den Thread-Pool auf etwas einstellen, das der Rechner verarbeiten kann und diejenigen, die nicht arbeiten, befinden sich stattdessen in einer Warteschlange herumlungern im Scheduler als schlafende Fäden. Es gibt etwas warten beschäftigt Verhalten, wenn niemand wirklich etwas tut, aber ich nehme von Ihrem Beitrag, dass der gesamte Zweck der Anwendung ist, diese Threads laufen und es ist derzeit Geländer Ihre Prozessoren. Möglicherweise müssen Sie das tun, wenn für andere Dinge Raum geschaffen werden muss:)

    
Affe 19.05.2010 19:16
quelle
-1

Sie benötigen ein Semaphor.

%Vor%

Wenn Sie die AThreads instanziieren, müssen Sie dieselbe Semaphor-Instanz übergeben:

%Vor%

Bearbeiten: Wer abgelehnt hat, kann bitte erklären warum? Es ist etwas falsch in meiner Lösung?

    
Andrea Polci 19.05.2010 18:45
quelle