2012-04-04 4 views
11

Ich schreibe ein Multithread-Java-Programm, bei dem jeder Thread seine Standardausgabe möglicherweise in eine separate Datei umleiten muss. Jeder Thread hätte seine eigene Datei. Ist es möglich, System.out auf einer "pro-Thread" -Basis umzuleiten oder sind Änderungen an System.out global über alle Threads hinweg?In einem Multithread-Java-Programm hat jeder Thread seine eigene Kopie von System.out?

+0

Sie können möglicherweise ein anderes 'PrintStream'-Objekt mit [AspectJ] (http://eclipse.org/aspectj) –

Antwort

21

Ist es möglich, System.out auf einer "pro-Thread" Basis

Nein, es ist nicht möglich, umzuleiten. System.out ist statisch und es gibt eine pro JVM, die als Teil des System-Classloaders geladen wird, wenn die JVM zu Beginn bootet. Obwohl natürlich die Verwendung geeigneter Protokollierungsaufrufe pro Thread empfohlen wird, nehme ich an, dass es Gründe gibt, warum Sie dies nicht tun können. Wahrscheinlich ist eine 3rd-Party-Bibliothek oder ein anderer Code, der auf diese Weise System.out verwendet.

Eine Sache, die Sie (als eine radikale Anregung) tun könnten, ist Ihre eigenen PrintStream, die an eine ThreadLocal<PrintStream> delegiert. Aber Sie müssen @Override alle Methoden aufrufen, um es per-Thread zu arbeiten.

Schließlich, wenn Sie das fragen, weil Sie über Gleichzeitigkeit besorgt sind, System.out ist ein PrintStream so ist es bereits synchronized unter der Decke und kann von mehreren Threads sicher verwendet werden.

+0

zurückgeben. Ich bin derzeit dabei, jeden Thread zu benennen und einen benutzerdefinierten PrintStream zu erstellen, der eine Map erstellt . Wenn der benutzerdefinierte Druckstream ein Signal empfängt, um etwas auf den Bildschirm zu drucken, verwendet er Thread.currentThread, um das aktuelle Thread-Objekt abzurufen und in der Karte nachzuschlagen. Wenn der Thread ein Schlüssel in der Map ist, wird die Ausgabe in den entsprechenden OutputStream geschrieben, andernfalls wird eine Standardausgabe ausgegeben. – user1258361

+1

Sie können java.util.logging (oder ein anderes Protokollierungsframework) mit einem geeigneten Formatierer verwenden, um den Namen des Threads zu protokollieren. Ich würde diesen Ansatz gegenüber der Verwendung von System.out dringend empfehlen. – Adamski

+0

Ich muss die Standardausgabe an einen variablen Speicherort umleiten, basierend darauf, welcher Thread ausgeführt wird. Die Threads geben keine standardmäßigen "Protokoll" -Fehlermeldungen aus. Ich habe Java Logging angeschaut und finde es nicht passend für mein Problem. – user1258361

3

System.out ist statisch und daher wird die gleiche Instanz zwischen allen Threads geteilt.

3

Sie haben Recht, aber nicht in der Art, wie Sie denken. Wenn ein Thread

verwendet
System.out.println(); 

Es dauert eine Kopie der ReferenzSystem.out, aber keine Kopie des Objekts dieser Referenzen.

Dies bedeutet, dass alle Threads normalerweise das gleiche Objekt zum Schreiben in die Ausgabe sehen.

Hinweis: Diese Felder sind nicht threadsicher und wenn Sie System.setOut(PrintStream) aufrufen Wenn Sie dies verwenden gibt es eine potentielle, unerwünschte Race-Bedingung, wo verschiedene Threads unterschiedliche lokale Kopien von System.out haben. Dies kann nicht verwendet werden, um diese Frage zu lösen.

Ist es möglich, System.out auf einer „pro-Thread“ Basis

Sie können dies tun, indem Sie ersetzen System.out mit Ihrer eigenen Implementierung zu umleiten, die spezifisch ist fädeln. eine Unterklasse von PrintStream. Ich habe dies für die Protokollierung getan, wo ich wollte, dass die Ausgabe jedes Threads konsistent und nicht verschachtelt ist. z.B. Stellen Sie sich vor, Sie drucken zwei Stapelspuren in zwei Threads gleichzeitig. ;)

+1

Du kannst es kontrollieren, bevor du weitere Threads startest, sonst musst du hoffen, dass es egal ist. Was meinst du damit? Junge, das ist irreführend? –

+0

Es gibt nur ein einziges System.out. Was Sie vorschlagen, ist, dass Sie System.out abhängig vom Thread ändern, was nicht dasselbe ist wie mehrere System.out. Ihr Vorschlag entspricht der Aussage, dass 8 CD-ROMs und ein einzelnes CD-ROM-Laufwerk 8 CD-ROM-Laufwerken entsprechen, da Sie die CD bei Bedarf austauschen können. Können CDs ausgeschaltet werden? Ja. Ist es das gleiche wie mit 8 CD-Laufwerken? Nein. – user1258361

+0

Ich schlage vor, Sie ändern die System.out zu einer Komponente, die auf einer Pro-Thread-Basis etwas anderes tut. Dies ist nicht dasselbe wie mehrere System.out-Werte. In meinem Kommentar ging es um die Thread-Sicherheit von System.out, die es mehreren Threads erlaubt, aufgrund einer Race Condition unterschiedliche Werte zu sehen, die Sie nicht verwenden können und die nur ein Problem darstellen. Ich schlage vor, einen 8-CD-Wechsler zu haben, der dem Benutzer als ein Laufwerk erscheint, z.B. mit 8 Unterverzeichnissen. –

5

Ist es möglich, System.out auf einer „pro-Thread“ Basis

Einige Entwickler von Maia Company zur Verfügung gestellt haben eine öffentliche Umsetzung eines Printumzuleiten, die ein „STDOUT“ bietet pro Thema in diesem Artikel: "Thread Specific System.out".

In ihrer Implementierung überschreiben sie nur Schreibmethoden, flush, close und checkError.Es scheint genug in ihrem Fall zu sein.

Sie tat nichtNotwendigkeit alle Methoden @Override genannt, um es pro Thread zu arbeiten“, wie @Gray in seiner Antwort erklärt.

+1

Scheint, dieser Link ist tot, aber Sie finden eine ähnliche Implementierung in 'org.apache.geronimo.gshell.support.gshell-io.SystemOutputHijacker' [Maven-Paket] (https://mvnrepository.com/artifect/org .apache.geronimo.gshell.support/gshell-io/1.0-alpha-2) und [Quellcode-Browser] (http://grepcode.com/file/repo1.maven.org/maven2/org.apache.servicemix. kernel.gshell/org.apache.servicemix.kernel.gshell.core/1.1.0/org/apache/geronimo/gshell/io/SystemOutputHijacker.java) –

0

Ist es möglich, System.out auf einer „pro-Thread“ Basis

Sie umleiten können sie alle auf Ihre Stellvertretung umleiten, die für verantwortlich sein wird ‚pro Thread‘ Logik.

Here is Beispiel für parallele JBehave-Tests mit eigener Dateiausgabe.

Verwandte Themen