2013-06-25 6 views
8

Wenn ein Java-Programm System.out.println() oder ein Scala-Programm aufruft, ruft println() den Threadblock auf?Wird die Konsolenausgabe blockiert?

Ich schreibe ein Scala-Programm mit einer großen Anzahl von Teilaufgaben. Jede Teilaufgabe wird innerhalb einer Zukunft ausgeführt. Es wird empfohlen, den Code innerhalb von Akteuren und Futures nicht zu blockieren, damit auch nachfolgende Aufgaben nicht warten müssen. Aber ich möchte sehr viel auf der Konsole drucken.

Und wenn es eine Blockierung ist: Was kann ich tun, um die Leistung zu optimieren?

  • Sollte ich einen dedizierten Thread für die Konsolenausgabe verwenden, so dass der Thread der einzige Block ist?
  • Weitere Ratschläge?
  • Natürlich könnte ich versuchen, die Menge der Ausgabe zu reduzieren oder einige Ausgaben in einem StringBuilder zu sammeln und sie in einem Stapel zusammen zu drucken, was die Anzahl der Ausgabevorgänge reduziert.

    Antwort

    12

    Wenn ein Java-Programm System.out.println() oder ein Scala-Programm aufruft, ruft println() den Threadblock auf?

    Ja und nein. System.out ist eine PrintStream, die eine synchronisierte Klasse ist. So werden mehrere Threads, die große Mengen an System.out schreiben, sich gegenseitig sicher blockieren. Sobald ein Thread die Sperre erhält, hängt es jedoch von der Architektur ab, ob der IO den Thread blockiert. Wenn Sie eine große Menge von IO schreiben, die die Kapazität der zugrunde liegenden Hardware überwältigt, dann wird blockieren. Eine Menge kleiner Schreibvorgänge (im Gegensatz zu gepuffert) verlangsamt auch den Thread.

    Sollte ich einen dedizierten Thread für die Konsolenausgabe verwenden, so dass der Thread der einzige ist, der blockiert?

    Ausgezeichnete Idee, ja. Dann könnte dieser Thread durch eine einzige BufferedWriter oder eine Art Log4j oder andere Logging-Paket schreiben, die im Vergleich zu System.out viel leistungsfähiger wäre. Sie müssen etwas wie eine BlockingQueue verwenden, um die Nachrichten in eine Warteschlange zu stellen, die synchron ist, aber die E/A wird diese Warteschlange niemals blockieren, es sei denn, Sie produzieren Nachrichten schneller als der E/A-Kanal sie persistieren kann.

    Natürlich könnte ich versuchen, die Menge der Ausgabe zu reduzieren oder einige Ausgaben in einem StringBuilder zu sammeln und zusammen in einem Stapel zu drucken, was die Anzahl der Ausgabevorgänge reduziert.

    Die BufferedWriter wird sich darum kümmern.

    Weitere Ratschläge?

    • Wie bereits erwähnt, verwendet, um ein bessere Protokollierung Paket oder einen Single-Threaded-Schriftsteller.
    • Schreiben Sie Protokolle auf eine andere physische Festplatte mit mehr E/A-Bandbreite.
    • Wechseln Sie zu einem Speicherdateisystem oder einer Hardware, um die E/A-Bandbreite zu erhöhen. SSD ++.
    • Senden Sie es über das Netzwerk an eine andere Box, um die tatsächliche ausbleibende Box zu tun.
    • Verwenden Sie eine GzipOutputStream, um es im laufenden Betrieb zu komprimieren.
    +0

    * Schreibprotokolle zu einem anderen Dateisystem. * Sie bedeuten unterschiedliche physisches Laufwerk? Oder wenn Sie meinen, dass ein Dateisystem für solche Aufgaben besser als ein anderes System optimiert ist (z. B. ext * versus btrfs), könnten Sie dann die Namen aufdecken? –

    +0

    Nein, ich meine wirklich IO-Kette, nicht anders FS-Typ @ om-nom-nom. Großer Benutzername BTW. :-) – Gray

    +0

    Dies. Dies ist eine gut formatierte und hilfreiche Antwort. – Andy

    4

    Es kommt auf. Auf Windows OS ist es eine blockierende Operation und beinhaltet eine Menge Kernel-Zeug, um etwas auf der Konsole zu drucken. In UNIX-wie OS ist die Operation gepuffert, so wird es nicht als langsam wahrgenommen.

    Ich würde vorschlagen, Sie gehen mit Ihrem Puffer-Ansatz, und mit einem separaten Thread ist auch eine gute Idee. Oder wenn Ihre Ausgabe nicht so wichtig ist, könnten Sie sie in eine Datei schreiben, die viel schneller ist als das Schreiben in die Konsole.

    +0

    Denken Sie auch daran, dass System.out nicht notwendigerweise auf die Konsole aus (es kann mit „command> out.txt“ in eine Datei umgeleitet wurden) – faffaffaff