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

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
PKeidel
Beiträge: 28
Registriert: 22.11.2007, 20:04

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

Beitrag 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 :)
Zuletzt geändert von PKeidel am 17.03.2011, 13:22, insgesamt 1-mal geändert.
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

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

Beitrag 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.
Benutzeravatar
The_Real_Black
Establishment
Beiträge: 110
Registriert: 19.01.2008, 19:57
Benutzertext: Happy Coding
Kontaktdaten:

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

Beitrag 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.
Happy Coding.
mär
Beiträge: 5
Registriert: 15.03.2011, 16:32

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

Beitrag 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
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4256
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

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

Beitrag 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)
Zuletzt geändert von Chromanoid am 18.03.2011, 11:47, insgesamt 1-mal geändert.
PKeidel
Beiträge: 28
Registriert: 22.11.2007, 20:04

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

Beitrag 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
MfG,
PKeidel
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4256
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

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

Beitrag 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 ^^
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

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

Beitrag 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
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4256
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

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

Beitrag von Chromanoid »

Genau. Callable/Runnable+ExecutorService ist ja die Java Standard Implementierung von dem Pattern...
Zuletzt geändert von Chromanoid am 18.03.2011, 11:34, insgesamt 1-mal geändert.
PKeidel
Beiträge: 28
Registriert: 22.11.2007, 20:04

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

Beitrag 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...
PKeidel
Beiträge: 28
Registriert: 22.11.2007, 20:04

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

Beitrag 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?
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4256
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

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

Beitrag 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);
        }
}
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

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

Beitrag 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
PKeidel
Beiträge: 28
Registriert: 22.11.2007, 20:04

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

Beitrag 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
Alexander Kornrumpf
Moderator
Beiträge: 2110
Registriert: 25.02.2009, 13:37

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

Beitrag 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)
Zuletzt geändert von Chromanoid am 18.03.2011, 11:53, insgesamt 1-mal geändert.
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4256
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

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

Beitrag 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.
PKeidel
Beiträge: 28
Registriert: 22.11.2007, 20:04

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

Beitrag 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^^
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4256
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

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

Beitrag von Chromanoid »

ja ich das ist beim testen entstanden :) ich musste doch phpbb modden...
Antworten