Seite 1 von 1

[JAVA] Threads sich selber zählen lassen

Verfasst: 25.09.2014, 12:54
von Oekel
Hi,
http://zfx.info/viewtopic.php?f=4&t=1457#p17525 habe ich gelesen, aber leider nicht ververnden können :(

Mein Problem ist, dass ich In einer Karte Gebäudedaten (OSM) lade. Im Idealfall habe ich diese Gebäude mit einer existierenden Wikipedia Seite verknüft. Dort wiederum hole ich mir die Bilder-URLs und möchte diese nun über dem jeweiligen Gebäude anzeigen lassen.

Soweit funktioniert es auch alles ;)
Doch da die Bilder relativ groß sind und das rezise in etwas wie 100x100 doch etwas Rechenzeit in Anspruch nimmt (es sind etwa 50-60 Bilder zu laden und zu cachen), habe ich den Ladeprozess pro Gebäude in einen separaten Thread gepackt, der sofort wieder zerstört wird, sobald das Bild geladen/gecached ist.

Nun laufe ich schön in eine "Exception in thread "Thread-172" java.lang.OutOfMemoryError: Java heap space", was auch soweit klar ist, da die Bilder teilweise riesig sind.
Nun möchte ich die Threads auf 5-10 Stück begrenzen, kann dies aber nicht von außen tun, da je nach Zoomstufe der Karte keine Stelle im Code existiert, wo ich diese schön brav hintereinader in 5 Threads abarbeiten könnte.
Ich möchte alle schon alle Threas "nahezu" gleichzeitig starten (wie bisher), denn diejenigen dessen url==null ist beenden sich eh sofort wieder.
Und nur in dem Fall, dass eine URL vorhanden ist, einen externen Counter hochzählen bzw. so lange warten, bis dieser wieder klein genug ist.

Doch wie mache ich das am besten?

Code: Alles auswählen

@Override
	public void run() {
		String url = f.getPreferedImageUrl();
		if (url == null)
			return;
		if (f.getImgTMP() == null && f.getImgTMPsvg() == null) {
			synchronized (this) {
				while (Parametric.drawConter > 5) {
					try {
						wait(200);
					} catch (InterruptedException e) {
					}
				}
				Parametric.drawConter++;

			}
			load....
			Parametric.drawConter--;
		}
	}
Aktuell scheint er bei 5 komplett zu stoppen und lädt die restlichen nicht wirklich nach.

Grüße Oekel

Re: [JAVA] Threads sich selber zählen lassen

Verfasst: 25.09.2014, 13:49
von xq
Mein Ansatz wäre jetzt einfach, n Workerthreads zu machen.

Du hast eine Klasse, die dir zum einen URL und zum anderen Bild speichert, nennen wir sie mal UrlImage
Zudem hast du einen Queue, in die du UrlImages enqueuest.

Deine n Workerthreads schnappen sich jetzt immer ein element aus der Queue und verarbeiten dieses. Sind sie fertig, speichern sie das geladene bild in das UrlImage zurück.
So kannst du Referenz auf das Bild halten, ohne dass es wirklich geladen sein muss.

Pseudo-Code:

Code: Alles auswählen

Queue<UrlImage> images;
UrlImage loadImage(string uri) {
    UrlImage img = new UrlImage(uri);
    images.enqueue(img);
    return img;
}

void startLoaders() {
   for(i = 1 to 10) {
      Thread.Run(imageLoadThread);
   }
}

void imageLoadThread() {
    while(true) {
        UrlImage img = images.dequeueOrNull();
        if(img != null) {
            img.image = download(img.url);
        }
        sleep(0)
    }
}
So würde ich das irgendwie lösen. Damit hast du eine begrenzte anzahl an threads, welche du nicht einmal neu starten musst, um die gesamte arbeit zu erledigen.

Grüße
Felix

Re: [JAVA] Threads sich selber zählen lassen

Verfasst: 25.09.2014, 13:56
von Oekel
Aber es geht ja auch ein wenig um's Prinzip. Es muss doch möglich sein einen Thread aus sich selbst heraus wenige ms schlafen zu legen und dann eine Variable neu zu prüfen?
Bisher sieht es mir so aus, als ob das wait()/schleep zwar von innen ausgelöst werden kann, aber das Aufwecken nicht. Muss ich das as "IST-SO" hinnehmen, oder gibt es dafür eine gute Erklärung?

Grüße Oekel

Re: [JAVA] Threads sich selber zählen lassen

Verfasst: 25.09.2014, 13:58
von xq
Thread.sleep sollte doch eigentlich nur eine gewisse Zeit warten und nicht den thread anhalten.

Ich würde dir trotzdem das Workerzeug ans Herz legen, da hast du wesentlich weniger gefrickel. Und du kannst, wenn du es richtig machst, das Zeug für alle möglichen asynchronen jobs verwenden (Thread Pooling)

Re: [JAVA] Threads sich selber zählen lassen

Verfasst: 25.09.2014, 14:02
von Krishty
Das ist, wie Felix sagt, der perfekte Anwendungsfall für Thread Pools. Du hast so viele Threads wie du effizient benutzen kannst (ähnlich der Anzahl Prozessorkerne) und die werden aktiviert, sobald es Arbeit für sie gibt.
Oekel hat geschrieben:Aber es geht ja auch ein wenig um's Prinzip. Es muss doch möglich sein einen Thread aus sich selbst heraus wenige ms schlafen zu legen und dann eine Variable neu zu prüfen?
Bisher sieht es mir so aus, als ob das wait()/schleep zwar von innen ausgelöst werden kann, aber das Aufwecken nicht. Muss ich das as "IST-SO" hinnehmen, oder gibt es dafür eine gute Erklärung?
Es ist deutlich effizienter. Ständiges Nachfragen nennt man Polling. Würden sich alle Threads regelmäßig selber aufwecken, könnte dein System unmöglich in einen Energiesparmodus wechseln, weil es dauernd arbeitet.

Re: [JAVA] Threads sich selber zählen lassen

Verfasst: 25.09.2014, 21:40
von Chromanoid
Warum kannst Du keine Thread-Pools nutzen? Genau für solche Fälle sind die doch da! Wenn Du einen bestimmten Download-Task "zwischendrin" unterbrechen willst, kannst Du mit der Future, die Du vom ExecutorService bekommst den Task abbrechen.