Anzeige:
Ergebnis 1 bis 9 von 9

Thema: Java, Threadgroup und Thread-Lebensdauer

  1. #1
    Registrierter Benutzer Avatar von BlueJay
    Registriert seit
    27.08.2004
    Beiträge
    825

    Java, Threadgroup und Thread-Lebensdauer

    Hallo Leute,

    da ist so ein Programmteil, welches eine Thread-Flut erzeugt. Diese kicken je eine Funktion mit je einem bestimmten Parameter an und sollen dann von der Bildfläche verschwinden.

    Soweit tun sie das auch, aber nach getaner Arbeit sind sie ziemlich zählebig.
    Bei der Erzeugung von 400-1000 Threads verschwinden sie noch ziemlich schnell aus der ThreadGroup (>50Stück /100ms), aber bei 5000 verdrücken sich nur laaaangsam (3-8/100ms).
    Laaangsam heisst, sie lümmeln gut doppelt so lange herum, wie sie für die Arbeit brauchten. Ich brauche den Speicher aber für was anderes!

    Der System-Monitor vom Betriebssystem zeigt in etwa dieselbe Bevölkerung an wie die Überwachung der Gruppe.

    Es bringt nichts, die Dinger auf null zu setzen, beim Abfragen der ThreadGroup ist da immer noch Hochbetrieb drin.

    Es bringt nichts, zusätzlich die GC aufzurufen.

    Thread.stop hat ebenfalls keinen Einfluß auf das Benehmen.

    Thread.destroy ist nicht vorhanden.

    Code:
    Code:
        int i,i0=0,blocksize=100;
        while(i0<symax)
        { try
          { for (i=0; i<blocksize; i++)
            { final int ii=i+i0;
              if (ii<symax)
              { Thread t=new Thread(tg,"zeile"+ii) { @Override public void run() { mach_zeile(ii); }; };
                t.start();
              }
            }
            i0=i0+blocksize;
          }
          catch(OutOfMemoryError e) { break; }
        }
    und
    Code:
     synchronized void mach_zeile(int zz)
      { double douzi=pot1min+zz*dzy;
        double douci=pot2min+zz*dcy;
        for (int ix=0; ix<sxmax; ix++)
        { gb.setColor(mycolor.get_color(ju.get_slope(kin1min+ix*dzx,douzi,kin2min+ix*dcx,douci)));
          gb.drawRect(ix,zz,1,1);
          Thread.yield(); // sonst blockiert GUI
        }
      }
    Hat jemand noch ein paar Tricks?

    Gruß,
    Ulrike
    Eigentlich ganz einfach, wenn man's weiss!

  2. #2
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Wenn du nicht gerade auf einem Cluster oder etwas ähnlichem arbeitest, ist eine so große Anzahl von Threads ohnehin nicht sehr sinnvoll.

    Einerseits weil das Erzeugen von Threads eine relativ kostspielige Operation ist und andererseits weil der Scheduler des Betriebsystems dann mehr zu tun hat, um zu entscheiden, wer auf welcher CPU dran kommt.

    Wenn du sehr viele ähnliche und unabhängige Aufgaben hast, ist wahrscheinlich das Arbeiten mit einem Threadpool effiezienter.

    http://konstantin.filtschew.de/blog/...rallelisieren/
    http://download.oracle.com/javase/tu...ncy/pools.html

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  3. #3
    Registrierter Benutzer Avatar von BlueJay
    Registriert seit
    27.08.2004
    Beiträge
    825
    Cluster? JA! BITTE!

    Da habe ich also die Arbeiten so zerhackt, dass man die Zeilengenerierung schön an Threads weiterreichen kann. Das gab einen irren Geschwindigkeitsvorteil.

    Nachteil: man muss jedem Thread einen speziellen Parameter mitgeben.
    Ich habe zwar herausbekommen, wie das beim Erzeugen geht, aber nicht, wie zwischendurch.

    Der Versuch der Wiederverwertung ergab einen java.lang.IllegalThreadStateException.

    Aber das Erzeugen und Durchführen von ca 5000 Threads war kein Problem für den Rechner, sondern die Geschichten wieder abzubauen.

    Also: einmal sind se tot, ein andermal nicht.
    Eigentlich ganz einfach, wenn man's weiss!

  4. #4
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Datenübergabe ist ansich kein Problem sofern man auf Sachen wie gleichzeitigen Zugriff Rücksicht nimmt. Man darf den Thread nur nicht aus der run() Method rauslassen (weil dann ist er zu Ende).

    Wie gesagt hört sich die Aufgabenstellung sehr nach einem Threadpool Use-case an.
    D.h. man gibt alle Aufgaben entsprechend parametriert in den Threadpool und überlässt diesem, sie auf seine Threads aufzuteilen.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  5. #5
    Registrierter Benutzer Avatar von BlueJay
    Registriert seit
    27.08.2004
    Beiträge
    825
    Hi,

    Genau das war mein Problem: run war zu Ende, die Threads aber noch da.

    Zudem wird wohl, was die Threadmenge angeht, was Falsches erzählt.
    Fakt ist, bei nur 8 Threads kann ich mir zeitmäßig die Mühe sparen, das Feld in Thread-Blöcken bearbeiten zu lassen. Der meldet zwar ruckzuck "bin fertig", aber das Bild ist noch im Aufbau, und das Ganze dauert fast so lange wie ohne Threads. Aber möglicherweise ist das prozessorabhängig.

    Einen Fehler habe ich gefunden: der Bildaufbau wurde doppelt gestartet. Das ist bei sequentieller Programmierung nicht problematisch gewesen, die function bekam sozusagen "on the fly" die neuen Parameter und Startwerte mit.
    Bei der Thread-Variante lagen etliche Zombies herum. Da kam die GC wohl nicht so einfach ran.

    Na, mal sehen, was mir noch zum Killen einfällt.
    Jedenfalls werde ich mir das mit dem Threadpool auch ansehen.

    Gruß,
    Ulrike
    Eigentlich ganz einfach, wenn man's weiss!

  6. #6
    Registrierter Benutzer Avatar von BlueJay
    Registriert seit
    27.08.2004
    Beiträge
    825
    sory, dass es so lange gedauert hat, mir ist eine grippe dazwischengekommen.


    Zu den Threadpools:
    Ja, sie kicken schön die Tasks an, geben auch sofort das Kommando an Swing/awt zurück.

    Auf den 1.Blick ist die Berechnung genauso schnell wie die der ThreadGroup, aber auch sie lassen sich nicht so einfach ausbremsen! Bei (versehentlichem) mehrfachern Betätigen des Calc-Buttons kommt es so zu einer Thread-Flut bis ummi 6000 einem Memory-Overflow.

    Der Vorteil dieser Konstruktion erschließt sich mir noch nicht so richtig, vor allem, weil er bei shutdown oder shutdownNow den Befehl verweigert.

    Dabei soll das Konstrukt doch nur alles stehen- und liegenlassen und die Ressourcen freigeben, wenn neue Parameter kommen!

    Aber vielleicht kommt der Aha-Effekt ja, wenn ich mal wieder an das 4-Prozessor-System darf

    Jetziger Code:
    Code:
     // try { my_pool.shutdown(); } catch(RejectedExecutionException e) { System.out.println("er will nicht"); }
        int i=0;
        while (i<symax)
        { final int ii=i;
          try
          { my_pool.execute(
                             new Thread() { @Override public void run() { mach_zeile(ii); }; }
                           );
            i++;
          }
          catch(OutOfMemoryError e) { System.out.println("wieder alles dicht!"); break; }
        }
    Gruß,
    Ulrike

    ach ja, my_pool ist ein newCachedThreadPool.
    Wenn man shutdownNow ans Rennen kriegt, reduzieren sich zwar die Threads, aber der Speicher wird nicht freigegeben
    Geändert von BlueJay (04-02-2011 um 10:30 Uhr) Grund: Info vergessen
    Eigentlich ganz einfach, wenn man's weiss!

  7. #7
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    So wie ich die Doku von shutdown() interpretiere, hilft dir das in der Tat nicht, weil es trotzdem alle schon angegebenen Aufgaben noch machen wird. Also bleibt nur shutdownNow().

    Frage zur Sicherheit: deine Thread Klasse ist kein Thread mehr, nur mehr ein Runnable, korrekt?

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  8. #8
    Registrierter Benutzer Avatar von BlueJay
    Registriert seit
    27.08.2004
    Beiträge
    825
    das ist richtig, so konnte ich mir ein paar mehr "Fehlklicks" leisten, bevor der OutOfMemory zuschlägt. Auch scheint er sich schneller davon "zu erholen".

    Und wie gesagt: shutdownNow verhindert die Thread-Explosion, aber nicht das OutOfMemory.

    irgendwo weiter oben:
    Code:
    try { my_pool.shutdownNow(); } catch(RejectedExecutionException e) { System.out.println("er will nicht"); }
        my_pool=Executors.newCachedThreadPool(); // sonst keine Task-Annahme
    Eigentlich ganz einfach, wenn man's weiss!

  9. #9
    Registrierter Benutzer Avatar von BlueJay
    Registriert seit
    27.08.2004
    Beiträge
    825
    Das Ding ist inzwischen auch als Runnabe deklariert

    Die ThreadPools sind in punkto Reaktivität der GUI was Feines.

    so habe jetzt mal mit FixedThreadPool gearbeitet, einen OutOfMemory konnte ich nicht mehr provozieren, aber die Berechnung ist langsamer geworden bei Drosselung von max. 2800 Tasks auf 1000. Der Speicherverbrauch bleibt unter 1GB, auch bei Calc-Button-Misshandlung.

    Und dass der Plakat-Aufbau im ungünstigsten Fall eine Dreiviertelstunde braucht, kann ich verschmerzen.

    Gruß,
    Ulrike
    Geändert von BlueJay (04-02-2011 um 15:36 Uhr) Grund: Versuch zuende
    Eigentlich ganz einfach, wenn man's weiss!

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •