2012-04-04 16 views
11

Piszę wielowątkowy program Java, w którym każdy wątek potencjalnie potrzebuje standardowego wyjścia przekierowanego do osobnego pliku. Każdy wątek miałby własny plik. Czy możliwe jest przekierowanie System.out na zasadzie "na wątek" lub czy zmiany w System.out global we wszystkich wątkach?W wielowątkowym programie Java, czy każdy wątek ma własną kopię System.out?

+0

Możesz być w stanie zwrócić inny obiekt 'PrintStream' używając [AspectJ] (http://eclipse.org/aspectj) –

Odpowiedz

21

Czy można przekierować System.out na zasadzie "per-thread"

Nie, to nie jest możliwe. System.out jest statyczny i jest jeden na maszynę JVM, która jest ładowana jako część programu ładującego klasy systemu, po początkowym rozruchu maszyny JVM. Chociaż oczywiście używanie odpowiednich zgłoszeń do logowania w wątku jest zalecane, zakładam, że istnieją powody, dla których nie możesz tego zrobić. Prawdopodobnie w ten sposób używa się biblioteki innej firmy lub innego kodu.

Jedną z rzeczy, które możesz zrobić (jako radykalną sugestię), jest utworzenie własnego PrintStream, który przenosi się na numer ThreadLocal<PrintStream>. Ale będziesz musiał @Override wszystkie metody wywoływane, aby uruchomić go na wątek.

Wreszcie, jeśli prosisz to dlatego, że są zaniepokojeni współbieżności, System.out jest PrintStream więc jest już synchronized pod kołdrą i może być bezpiecznie stosowany przez wielu wątków.

+0

Aktualnie szukam nazw dla każdego wątku i tworzenia niestandardowego strumienia Strumienia, który pobiera mapę . Kiedy niestandardowy strumień wydruku otrzymuje sygnał do drukowania czegoś na ekranie, używa Thread.currentThread do pobrania bieżącego obiektu Thread i wyszukuje go na mapie. Jeśli wątek jest kluczem na mapie, dane wyjściowe są zapisywane w odpowiednim strumieniu wyjściowym, w przeciwnym razie dochodzi do domyślnego wyniku. – user1258361

+1

Możesz użyć java.util.logging (lub innej struktury logowania) z odpowiednim formaterem, aby zarejestrować nazwę wątku. Zdecydowanie poleciłbym to podejście w stosunku do używania System.out. – Adamski

+0

Muszę przekierować standardowe wyjście do zmiennej lokalizacji na podstawie tego, który wątek jest uruchomiony. Wątki nie wyprowadzają standardowych komunikatów o błędach "log". Spojrzałem na Logging Java i nie sądzę, że jest to właściwe dla mojego problemu. – user1258361

3

System.out jest statyczny, dlatego ta sama instancja jest współużytkowana między wszystkimi wątkami.

3

Masz rację, ale nie w sposób, w jaki myślisz. Gdy wątek używa

System.out.println(); 

Zajmuje kopię odniesieniaSystem.out, ale nie kopię obiektu to referencje.

Oznacza to, że wszystkie wątki będą normalnie widzieć ten sam obiekt do zapisu do wydruku.

Uwaga: To pole nie jest bezpieczne dla wątków i jeśli zadzwonisz pod numer System.setOut(PrintStream) Jeśli używasz tego, istnieje potencjalny, niepożądany stan wyścigu, w którym różne wątki mają różne lokalne kopie System.out. Nie można tego użyć do rozwiązania tego pytania.

Czy można przekierować System.out na zasadzie „per-thread”

Można to zrobić poprzez zastąpienie System.out z własnej implementacji, która jest specyficzna nić. to jest podklasa klasy PrintStream. Zrobiłem to dla logowania, gdzie chciałem, aby każdy wynik wątku był spójny i nie był przeplatany. na przykład Wyobraź sobie drukowanie dwóch śladów stosu w dwóch wątkach w tym samym czasie. ;)

+1

Możesz kontrolować to moje ustawienie przed rozpoczęciem kolejnych wątków, w przeciwnym razie musisz mieć nadzieję, że to nie ma znaczenia. Co masz na myśli, mówiąc: "Chłopak to wprowadza w błąd"? –

+0

Istnieje tylko jeden System.out. Sugerujesz, że zmieniasz System.out w zależności od wątku, który nie jest tym samym, co wielokrotne System.out. Twoja sugestia jest analogiczna do stwierdzenia, że ​​posiadanie 8 napędów CD-ROM i pojedynczego napędu CD-ROM jest równoznaczne z posiadaniem 8 napędów CD-ROM, ponieważ w razie potrzeby można wyłączyć płytę CD. Czy płyty CD mogą zostać wyłączone? Tak. Czy to to samo, co posiadanie 8 napędów CD? Nie. – user1258361

+0

Proponuję zmienić System.out na komponent, który robi coś innego na podstawie wątku. To nie jest to samo, co posiadanie wielu wartości System.out. Mój komentarz dotyczył bezpieczeństwa wątków System.out, który pozwala wielu wątkom widzieć różne wartości ze względu na stan wyścigu, coś, czego nie można użyć i byłoby tylko problemem. Sugeruję posiadanie 8 zmieniacza CD, który pojawia się jako jeden dysk dla użytkownika, np. z 8 podkatalogami. –

5

Czy można przekierować System.out na zasadzie "per-thread"

Niektórzy programiści z Maia Company dostarczyły publicznego realizację PrintStream który zapewnia jeden "STDOUT" na wątek w tym artykule: "Thread Specific System.out".

W swojej implementacji zastępują tylko metody zapisu, opróżniania, zamykania i sprawdzania błędów.W ich przypadku wystarczy.

one niepotrzebę @Override wszystkich metod zwanych aby zmusić go do pracy per-thread” jako @Gray zamieszczonego w swojej odpowiedzi.

+1

Wygląda na to, że ten link nie działa, ale podobną implementację można znaleźć w 'org.apache.geronimo.gshell.support.gshell-io.SystemOutputHijacker' [Pakiet Maven] (https://mvnrepository.com/artifact/org .apache.geronimo.gshell.support/gshell-io/1.0-alpha-2) i [przeglądarka kodu źródłowego] (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

Czy można przekierować System.out na zasadzie „per-thread”

można przekierować je wszystkie do swojego delegata, który będzie odpowiedzialny za logikę „per-thread”.

Here is przykład równoległych testów JBehave mających własne wyjście pliku.

Powiązane problemy