3

I am trying to write to a file. I need to be able to "append" to the file rather than write over it. Also, I need it to be thread safe and efficient. The code I have currently is:

private void writeToFile(String data) {
    File file = new File("/file.out");
    try {
      if (!file.exists()) {
        //if file doesnt exist, create it
        file.createNewFile();
      }
      PrintStream out = new PrintStream(new FileOutputStream(file, true));
      DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
      Date date = new Date();
      out.println(dateFormat.format(date) + " " + data);

      out.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

It all works great. I just do not know if PrintStream is thread-safe or not. So, my question: Is writing to the same physical file from several instances of PrintStream safe? If so, does it use locking (reduces performance) or queueing? Do you know of any native java libraries that are thread-safe and use queueing? If not I have no problem writing my own. I am simply trying to see if there is anything native before I go write my own.

Nick Humrich
  • 14,905
  • 8
  • 62
  • 85
  • `PrintStream`'s methods are `synchronized`. Queueing is achieved via the write buffer. – Marko Topolnik Feb 07 '14 at 16:15
  • 3
    the thread safety of PrintStream in itself does not matter in your case since you only access it through a local instance. Did you mean to ask if writing to the same physical file from several instances of PrintStream is safe? – assylias Feb 07 '14 at 16:15
  • @assylias yes. Thanks for the correction. I will edit my question to represent that. – Nick Humrich Feb 07 '14 at 16:16
  • http://stackoverflow.com/questions/128038/how-can-i-lock-a-file-using-java-if-possible – assylias Feb 07 '14 at 16:20
  • do not use multiple printstream instances. just look how loggers works - one thread (consumer) is constantly writing to file, other threads use blocking queue to give him a work (producers). – Maciej Dobrowolski Feb 07 '14 at 16:23
  • @MaciejDobrowolski I think blockingQueue's are going to be my answer. Thanks for the suggestion. – Nick Humrich Feb 07 '14 at 16:24

1 Answers1

3

The PrintStream source suggests that it is thread safe.

If you want to write to the same file from different threads, why not share the same PrintStream instance across the threads? The PrintStream does the syncing for you.

/**
 * Prints a String and then terminate the line.  This method behaves as
 * though it invokes <code>{@link #print(String)}</code> and then
 * <code>{@link #println()}</code>.
 *
 * @param x  The <code>String</code> to be printed.
 */
public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}
anonymous
  • 1,317
  • 8
  • 7
  • the lock is per instance - the question involves several instances. – assylias Feb 07 '14 at 16:19
  • Thats an idea I have thought off, but if I do that, will it use locking or queueing? – Nick Humrich Feb 07 '14 at 16:23
  • @assylias Sorry it wasn't clear that OP wanted several instances writing to the same file at the beginning. But now that it is clear, I wonder if it's good idea to have multiple instances writing to the same file. What are the benefits of doing so compared to single instance shared among different threads? – anonymous Feb 07 '14 at 16:26
  • @anonymous There is no specific reason why I have multiple instances instead of a single instance. However, having a single instance doesn't really buy me much unless it uses queued blocking rather than locked blocking. – Nick Humrich Feb 07 '14 at 16:31
  • @humdinger, sorry, but what is queued blocking vs locked blocking? Maybe I'll ask another question. How do you want the multiple threads to behave when writing to the same file? In queuing, I thought you might want the thread write "data" but not have to block for I/O and get back to work straightaway to fetch more data to write. Is this the intention? – anonymous Feb 07 '14 at 16:36
  • If this is the intention, you can implement a point of contact for the threads to write to and this guy just buffers and write in batches into the file. So the threads don't wait for I/O. The I/O pain is bore by a single guy who writes to file. – anonymous Feb 07 '14 at 16:44
  • @anonymous that is exactly was I was wanting. where the data gets "queued" for I/O and the threads continue doing what they were doing even if the file is currently locked. I think I am just going to have to implement a blocking queue to do this. – Nick Humrich Feb 07 '14 at 16:49