Seite 1 von 1

[Java] [Gelöst] Mehrere Threads, max Anzahl begrenzen

Verfasst: 16.03.2011, 14:45
von PKeidel
Hi,

ich habe ein kleines Java (logik) Problem und bräuchte mal ein paar pfiffige Leute mit guten Einfällen ;)

SItuation:
- Ich habe ca. 30-40 Threads die sehr rechenintensiv sind
- um den Rechner etwas zu schonen möchte ich, dass immer nur max. 5 Stück gleichzeitig laufen
- sobald einer fertig ist soll der nächste (aus der Warteleiste) gestartet werden

Mein Problem:
Wenn ich die Threads in einer Schleife wie hier starte:

Code: Alles auswählen

Thread scn[] = new Thread[dirs.size()];
for (File f : dirs)
{
	scn[z] = new Scanner(f);
}

for (int aktID = 0; aktID < 5; aktID++)
{
	scn[aktID].start();
	System.out.println("scn[" + aktID + "].start();");
}

for (int aktID = 0; aktID < 5; aktID++)
{
	scn[aktID].join();
	System.out.println("scn[" + aktID + "].join();");
}
dann wartet das Programm ja bis alle 5 Threads fertig sind. Wie bekomme ich es also hin das der Thread scn[5] gestartet wird wenn einer der Threads scn[0-4] fertig ist? Und wenn dann wieder einer fertig ist soll der Thread scn[6] gestartet werden, usw, usw, usw...

Vermutlich ist es ganz einfach und ich sitze schon zulange davor um die Lösung zu finden :(


Meine Vermutung ist:
Ich benötige einen EventListener in der Klasse Scanner der anschlägt sobald er fertig ist. Wenn dieses Event ausgelöst wird muss in der Main Klasse der nächste Thread gestartet werden. Der "scn[x].join()"-Bereich würde dann wegfallen, da er duch das "Fertig"-Event abgelöst wird.

Liege ich mit der Vermutung richtig oder wäre das so nicht möglich? Oder gibts noch was besseres?


Schon Mal danke für die Hilfe :)

Re: [Java] Mehrere Threads, aber es sollen immer max. 5 lauf

Verfasst: 16.03.2011, 14:48
von Aramis
Starte keine 30-40 Threads, sondern nur 5. Denn genau soviele willst du ja gleichzeitig am Laufen haben. Schieb alle Jobs in eine zentrale Queue und lass diese 5 Threads nonstop neue Jobs abholen und abarbeiten.

Re: [Java] Mehrere Threads, aber es sollen immer max. 5 lauf

Verfasst: 16.03.2011, 14:49
von The_Real_Black
SItuation:
- Ich habe ca. 30-40 Threads die sehr rechenintensiv sind
- um den Rechner etwas zu schonen möchte ich, dass immer nur max. 5 Stück gleichzeitig laufen
- sobald einer fertig ist soll der nächste (aus der Warteleiste) gestartet werden
Liegt das Ergebnis erst vor wenn alle Threads fertig sind oder kann man die Teilergebnisse nutzen??
Wenn sie erst am ende vorliegen kannst du alle Threads laufen lassen, dann kümmert sich der Rechner bzw das OS ganz alleine darum die Threads durch zu wechseln.

Re: [Java] Mehrere Threads, aber es sollen immer max. 5 lauf

Verfasst: 16.03.2011, 16:09
von mär
Also ich kenne die Syntax nicht, aber es ist wirklich ziemlich einfach zu realisieren. Einfach die Threads der Reihe nach durchgehen und beim jeweils nächsten Thread solange warten, bis weniger als 5 Threads gestartet sind.

So also:

Code: Alles auswählen

for i = 0 to Threadlistencount
  Thread [i] -> start
  
  repeat
    cnt = 0;
    for j = 0 to i
      if Thread [j]. Aktiv
        cnt++;
    end for
  until cnt < 5
end for

Re: [Java] Mehrere Threads, aber es sollen immer max. 5 lauf

Verfasst: 16.03.2011, 16:22
von Chromanoid
http://download.oracle.com/javase/1.5.0 ... utors.html
Also:

Code: Alles auswählen

ExecutorService e=Executors.newFixedThreadPool(5);
for(Runnable r:runnables){
  e.execute(r);
}
Arbeite lieber mit Runnable oder Callable statt Thread.
Dein Code mit Executor:

Code: Alles auswählen

ExecutorService e=Executors.newFixedThreadPool(5);
ArrayList<Scanner> scn=new ArrayList<Scanner>();
for (File f : dirs){
        scn.add(new Scanner(f));
}
e.invokeAll(scn,10L, TimeUnit.MINUTES);
e.shutdown();
Scanner sollte dann Callable sein...
(edit: test)

Re: [Java] Mehrere Threads, aber es sollen immer max. 5 lauf

Verfasst: 16.03.2011, 19:31
von PKeidel
Hi,

ich danke euch allen für die Hilfe!

Code: Alles auswählen

ExecutorService e = Executors.newFixedThreadPool(5);
int z = 0;
for (File f : dirs)
{
	final Scanner s = new Scanner(f);
	z++;
	e.submit(new Runnable()
	{
		public void run()
		{
			s.start();
			s.join();
		}
	});
}
e.shutdown();
e.awaitTermination(2, TimeUnit.DAYS);
funktioniert...denke ich. Der Test läuft heute die Nacht über.

MfG,
PKeidel

Re: [Java] Mehrere Threads, aber es sollen immer max. 5 lauf

Verfasst: 16.03.2011, 19:36
von Chromanoid
Du solltest das noch mal überarbeiten :) ich hatte da zu erst mist geschrieben ^^. Momentan startet jetzt jeder Thread im Threadpool einen neuen Thread. D.h. du hast immer 10 Threads laufen. Wie gesagt es wäre besser wenn dein Scanner nicht von thread erbt, sondern Callable<Object> implementiert. Ich hab in meinem post noch mal editiert, wie es optimal wäre ^^

Re: [Java] Mehrere Threads, aber es sollen immer max. 5 lauf

Verfasst: 16.03.2011, 21:50
von kimmi
Such in diesem Zusammenhang mal nach dem Master / Worker-Pattern im Inet. Das ist eine Standard-Lösung für dieses Problem und ist bestens dokumentiert ( auch mit Java-Beispielen ).

Gruß Kimmi

Re: [Java] Mehrere Threads, aber es sollen immer max. 5 lauf

Verfasst: 16.03.2011, 22:00
von Chromanoid
Genau. Callable/Runnable+ExecutorService ist ja die Java Standard Implementierung von dem Pattern...

Re: [Java] Mehrere Threads, aber es sollen immer max. 5 lauf

Verfasst: 17.03.2011, 09:13
von PKeidel
Chromanoid hat geschrieben:Ich hab in meinem post noch mal editiert
Tatsächlich...ist mir gar nicht mehr aufgefallen^^. Wieso wird das nicht im Post angezeigt? Oder find ichs nur net? Also ne Info das dus nomma im Nachhinein bearbeitet wurde.... Ich kenne das dann mit dem Hinweis "Dieser Betrag wurde von .... am ... um ... Uhr bearbeitet."
Chromanoid hat geschrieben:Du solltest das noch mal überarbeiten
hmm..nagut^^ Dann werde ich das mal machen...

Re: [Java] Mehrere Threads, aber es sollen immer max. 5 lauf

Verfasst: 17.03.2011, 10:16
von PKeidel
So, das Programm läuft und ich hab etwas Zeit um meinen aktuellen Stand mal schriftlich festzuhalten^^:
Scanner.java hat geschrieben:

Code: Alles auswählen

public class Scanner implements Callable<Boolean>
{
	boolean isFinished = false;

	[...]

	public void run()
	{
		// hier en morz mäßiges Programm^^
		isFinished = true;
	}

	public Boolean call() throws Exception
	{
		run();
		return isFinished;
	}
}
Starter.java hat geschrieben:

Code: Alles auswählen

public class Starter
{
	[...]

	private void go() throws InterruptedException
	{
		System.out.println("Insg. " + dirs.size() + " Threads starten für:");

		ExecutorService e = Executors.newFixedThreadPool(1);
		ArrayList<Scanner> scn = new ArrayList<Scanner>();
		for (File f : dirs)
		{
			scn.add(new Scanner(f));
		}
		e.invokeAll(scn, 2, TimeUnit.DAYS);
		e.shutdown();

		System.out.println("_________________________\nAlle Scans sind fertig!");
		System.exit(0);
	}

	[...]
}
Meine Frage jetzt: Würde das so passen? Oder passt wieder irgendwas net?

Re: [Java] Mehrere Threads, aber es sollen immer max. 5 lauf

Verfasst: 17.03.2011, 12:57
von Chromanoid
ExecutorService e = Executors.newFixedThreadPool(1);
Erzeugt einenThreadPool mit einem Thread, ich dachte du wolltest 5?

Die Funktion run() ist im Scanner unnötig. Callable<V> ist ein Interface, das vorgibt, dass eine Klasse die Funktion V call() unterstützt. Das wäre das Kommando im Kommando Entwurfsmuster und zusammen mit dem ExecutorService wird das dann zum Master/Worker Muster. Du entkoppelst so die konkrete Ausführung eines Kommandos vom Aufrufen des Kommandos. Es gibt Callable und Runnable in Java. Runnable ist zusammen mit Executor die lite Variante, die keine Rückgabewerte kennt. Der Rückgabewert von Callable#call wir bei Ausführung durch einen ExecutorService in ein Future Objekt gekapselt, so dass man damit auch schon bevor die Ausführung abgeschlossen ist "arbeiten" kann. Da du keine Rückgabewerte brauchst, kannst du null in call zurückgeben. Sollte der Scanner irgendwas zurückgeben, kannst du das tun und im Nachhinein über die Future per get abholen. Über get kommst du dann auch an die Exception, die call evt. zum Abbrechen gebracht hat.
Wenn du lieber nur run benutzen willst, kannst du einfach nur Runnable implementieren, call entfernen und das so machen:

Code: Alles auswählen

public class Scanner implements Runnable{
        public void run() {
                // hier en morz mäßiges Programm^^
        }
}
public class Starter {
        private void go() {
                System.out.println("Insg. " + dirs.size() + " Threads starten für:");
                ExecutorService e = Executors.newFixedThreadPool(5);              
                for (File f : dirs) {
                        e.execute(new Scanner(f));
                }                
                e.shutdown();
                es.awaitTermination(2, TimeUnit.DAYS);
                System.out.println("_________________________\nAlle Scans sind fertig!");
                System.exit(0);
        }
}

Re: [Java] Mehrere Threads, aber es sollen immer max. 5 lauf

Verfasst: 17.03.2011, 13:18
von kimmi
Und mit einer Queue kannst du die dann noch miteinander reden lassen, wenn du so etwas brauchen kannst: http://www.developer.com/java/ent/artic ... gQueue.htm

Gruß Kimmi

Re: [Java] Mehrere Threads, aber es sollen immer max. 5 lauf

Verfasst: 17.03.2011, 13:21
von PKeidel
Chromanoid hat geschrieben:ExecutorService e = Executors.newFixedThreadPool(1);
Erzeugt einenThreadPool mit einem Thread, ich dachte du wolltest 5?
Öhm...jop. Hatte da zum Testen mal ne 1 rein geschrieben, bzw. heißt die Zeile bei mir
ExecutorService e = Executors.newFixedThreadPool(startAnz);
und ich hatte die Variable startAnz auf 1 gesetzt^^

Die Funktion in Callable mit dem Rückgabewert ist ganz praktisch, dann kann ich mir einen Zwischenspeicherungs-Schritt in die Datenbank sparen :)

Also das Programm läuft jetzt so wies soll :) Perfekt, vielen Dank!


MfG,
PKeidel

Re: [Java] [Gelöst] Mehrere Threads, max Anzahl begrenzen

Verfasst: 18.03.2011, 10:18
von Alexander Kornrumpf
Wieso wird das nicht im Post angezeigt?
Ich schätze mal Moderatoren können "geheim" editieren, ob man das irgendwo an/abschalten kann weiß ich allerdings nicht.

(edit: test)

Re: [Java] [Gelöst] Mehrere Threads, max Anzahl begrenzen

Verfasst: 18.03.2011, 11:07
von Chromanoid
Alexander Kornrumpf hat geschrieben:
Wieso wird das nicht im Post angezeigt?
Ich schätze mal Moderatoren können "geheim" editieren, ob man das irgendwo an/abschalten kann weiß ich allerdings nicht.
Also das würde mich wundern :). Soweit ich das erlebt habe, kommt die Editiernachricht immer dann wenn schon was neues geschrieben wurde. Solange man die letzte Antwort editiert, kommt keine Nachricht. Gleich mal ausprobieren ^^
Tatsächlich das Editieren wurde nicht angezeigt, mmh das ist aber doof, einstellen kann ich das nämlich nicht und jedes mal explizit den Grund angeben wäre doch sehr unpraktisch. Ich schau mal was da intern passiert.

Es war tatsächlich so, dass Moderatoren das nicht abstellbare Privileg hatten, ohne Anzeige ändern zu können. Ab jetzt wird bei jedem eine Editier-Nachricht angezeigt, wenn nicht der letzte Post editiert wird.

Re: [Java] [Gelöst] Mehrere Threads, max Anzahl begrenzen

Verfasst: 18.03.2011, 22:08
von PKeidel
Ha! Wer wars? Erwischt :P Jetzt steht wieder "Zuletzt geändert von Chromanoid am 18.03.2011, 11:47, insgesamt 1-mal geändert." drunter^^

Re: [Java] [Gelöst] Mehrere Threads, max Anzahl begrenzen

Verfasst: 18.03.2011, 23:42
von Chromanoid
ja ich das ist beim testen entstanden :) ich musste doch phpbb modden...