In a multithreaded Java program, does each thread have its own copy of System.out? In a multithreaded Java program, does each thread have its own copy of System.out? multithreading multithreading

In a multithreaded Java program, does each thread have its own copy of System.out?


Is it possible to redirect System.out on a "per-thread" basis

No it is not possible. System.out is static and there is one per JVM that is loaded as part of the system classloader when the JVM initially boots. Although of course using proper logging calls per-thread is recommend, I assume there are reasons why you can't do this. Probably a 3rd party library or other code is what is using System.out in this manner.

One thing you could do (as a radical suggestion) is to make your own PrintStream that delegates to a ThreadLocal<PrintStream>. But you will need to @Override the appropriate methods called by your application to get it to work per-thread.

Lastly, if you are asking this because you are worried about concurrency, System.out is a PrintStream so it is already synchronized under the covers and can be used safely by multiple threads.


Is it possible to redirect System.out on a "per-thread" basis

Some developers from Maia Company have provided a public implementation of a PrintStream that provides one "STDOUT" per thread in this article : "Thread Specific System.out".

In their implementation they override only write methods, flush, close and checkError. It seems to be enough in their case.

They did not "need to @Override all of the methods called to get it to work per-thread" as @Gray stated in his answer.


NOTA:

Please find below the original code from Maia.

I found it here on the wayback machine. The original page was removed from the website of Maia. I reproduce it here for the reader's curiosity. I do not provide any support for this code.


Main.java

Creates a ThreadPrintStream, installs it as System.out, and creates and starts 10 threads.

public class Main {  public static void main(String[] args) {    // Call replaceSystemOut which replaces the    // normal System.out with a ThreadPrintStream.     ThreadPrintStream.replaceSystemOut();    // Create and start 10 different threads.  Each thread    // will create its own PrintStream and install it into    // the ThreadPrintStream and then write three messages    // to System.out.    for (int i = 0;  i < 10;  i++) {      Thread thread = new Thread(new StreamText());      thread.start();      // Report to the console that a new thread was started.      System.out.println("Created and started " + thread.getName());    }  }}

StreamText.java

A simple Runnable for each thread that opens a file for the thread’s output and installs it into the ThreadPrintStream.

import java.io.BufferedOutputStream;import java.io.FileOutputStream;import java.io.PrintStream;/** A small test class that sets System.out for the currently executing * thread to a text file and writes three messages to System.out. */public class StreamText implements Runnable {  @Override  public void run() {    try {      // Create a text file where System.out.println()      // will send its data for this thread.      String name = Thread.currentThread().getName();      FileOutputStream fos = new FileOutputStream(name + ".txt");      // Create a PrintStream that will write to the new file.      PrintStream stream = new PrintStream(new BufferedOutputStream(fos));      // Install the PrintStream to be used as System.out for this thread.      ((ThreadPrintStream)System.out).setThreadOut(stream);      // Output three messages to System.out.      System.out.println(name + ": first message");      System.out.println("This is the second message from " + name);      System.out.println(name + ": 3rd message");      // Close System.out for this thread which will      // flush and close this thread's text file.      System.out.close();    }    catch (Exception ex) {      ex.printStackTrace();    }  }}

ThreadPrintStream.java

Extends java.io.PrintStream. An object of ThreadPrintStream replaces the normal System.out and maintains a separate java.io.PrintStream for each thread.

import java.io.ByteArrayOutputStream;import java.io.PrintStream;/** A ThreadPrintStream replaces the normal System.out and ensures * that output to System.out goes to a different PrintStream for * each thread.  It does this by using ThreadLocal to maintain a * PrintStream for each thread. */public class ThreadPrintStream extends PrintStream {  /** Changes System.out to a ThreadPrintStream which will   * send output to a separate file for each thread. */  public static void replaceSystemOut() {    // Save the existing System.out    PrintStream console = System.out;    // Create a ThreadPrintStream and install it as System.out    ThreadPrintStream threadOut = new ThreadPrintStream();    System.setOut(threadOut);    // Use the original System.out as the current thread's System.out    threadOut.setThreadOut(console);  }  /** Thread specific storage to hold a PrintStream for each thread */  private ThreadLocal<PrintStream> out;  private ThreadPrintStream() {    super(new ByteArrayOutputStream(0));    out = new ThreadLocal<PrintStream>();  }  /** Sets the PrintStream for the currently executing thread. */  public void setThreadOut(PrintStream out) {    this.out.set(out);  }  /** Returns the PrintStream for the currently executing thread. */  public PrintStream getThreadOut() {    return this.out.get();  }  @Override public boolean checkError() {    return getThreadOut().checkError();  }  @Override public void write(byte[] buf, int off, int len) {    getThreadOut().write(buf, off, len);  }  @Override public void write(int b) { getThreadOut().write(b); }  @Override public void flush() { getThreadOut().flush(); }  @Override public void close() { getThreadOut().close(); }}


You are right but not in the way you think. When a thread uses

System.out.println();

It takes a copy of the reference System.out, but not a copy of the object this references.

This means all threads will normally see the same object for writing to output.

Note: This fields in not thread safe and if you call System.setOut(PrintStream) If you use this there is a potential, undesirable race condition where different threads to have different local copies of System.out. This cannot be used to solve this question.

Is it possible to redirect System.out on a "per-thread" basis

You can do this by replacing System.out with your own implementation which is thread specific. i.e. a sub class of PrintStream. I have done this for logging where I wanted each thread's output to be consistent and not interleaved. e.g. Imagine printing two stack traces in two threads at the same time. ;)