Is it safe to call write
on Java FileOutputStream
object form multiple threads? Will the output be serialized correctly?
clarification:
In my case the class logger holds a FileOutputStream reference, and multiple threads can call logger write, that formats the output and calls FileOutputStream write.
Should I synchronize my logger write method to warrant that the messages from multiple threads are not mixed?
Here is a simple implementation of a synchronized logger using the java nio FileChannel. In this example, log messages are limited to 1024 bytes. You can adjust the log message length by changing the BUFFER_SIZE value.
This is how you would use it :
No. Java does not support streaming to the same stream from multiple threads.
If you want to do use threaded streams, check out this site: http://lifeinide.com/post/2011-05-25-threaded-iostreams-in-java/
He explains things well and has some sample code for a
ThreadedOutputStream
, which would do what you want.If you want to keep ordering (ie message 1 in the output stream came before message 2) you have to lock the stream. This in turn reduces concurrency. (All threads will be enqueued in the lock's/semaphore's queue and wait there for the stream to become available to them)
If you're interested only in writing to a stream concurrently and don't care about ordering, you can have buffers for each thread. Each thread writes to its own buffer. When the buffer is full it acquires a lock (which may involve waiting for the lock) on the stream and empties its contents into the stream.
Edit: I just realized that, if you care about ordering and still want multi-threading, if you also write the time in the output stream in unix format (as a long). After the stream is flushed onto some other container, the contents can be sorted based on time and you should have an ordered file.
A file can not be opened more than once in
write-mode
, so the answer is no.After seeing your edit, yes you should introduce synchronization into your logger to make sure the stream is accessed only by one thread at a time. Just a suggestion, why don't you go for Log4J? It already handles your use case.