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?
Odpowiedz
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.
Aktualnie szukam nazw dla każdego wątku i tworzenia niestandardowego strumienia Strumienia, który pobiera mapę
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
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
System.out
jest statyczny, dlatego ta sama instancja jest współużytkowana między wszystkimi wątkami.
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. ;)
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"? –
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
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. –
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 nie „potrzebę @Override wszystkich metod zwanych aby zmusić go do pracy per-thread” jako @Gray zamieszczonego w swojej odpowiedzi.
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) –
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.
Możesz być w stanie zwrócić inny obiekt 'PrintStream' używając [AspectJ] (http://eclipse.org/aspectj) –