Why FileChannel in Java is not non-blocking? - java

I wanted to write a program which writes to multiple files simultaneously; thought it will be possible with one thread by using non-blocking mode. But FileChannel does not support non-blocking mode. Does anybody know why?

UNIX does not support non-blocking I/O for files, see Non-blocking I/O with regular files. As Java should (at least try to) provide the same behaviour on all platforms, the FileChannel does not implement SelectableChannel.
However Java 7 will include a new AsynchronousFileChannel class that supports asynchronous file I/O, which is a different mechanism to non-blocking I/O.
In general only sockets and pipes truly support non-blocking I/O via select() mechanism.

Simply put, most operating systems doesn't treat regular files as something that can block - so they don't allow you explicitly set them to a non-blocking state.

Related

Non-blocking Async IO in Java

Is there any way to do asynchronous IO in Java without blocking any threads (including background threads)? Coming from C#, my understanding of async IO is that it when you call
await ReadAsync()
The calling thread (part of a threadpool) steps into the ReadAsync function, at some point calls an asynchronous read function from the OS kernel, and then adds itself back to the threadpool to pick up other Tasks. Once the read is completed, the threadpool is notified and another thread picks up the rest of the Task.
In Java, on the other hand, the documentation and this answer seem to suggest that asynchronous IO functions are simply called by a background thread that then blocks. This seems less performant. Is there any way to achieve true, non-blocking IO in Java?
The AsynchronousFileChannel.open() returns instances of different implementations according to the running environment. On Windows it should return an instance of WindowsAsynchronousFileChannelImpl which uses I/O completion port and avoids blocking threads on IO operations. Threads of thread pool are only used to dispatch results and do not block, unless the end user programmer blocks that thread.
The RxIo is built on top of AFC and provides the AsyncFiles equivalent to the synchronous Files class but with an asynchronous API. Taking advantage of the continuation-passing style of CompletableFuture (equivalent to .net Task) you may read a file content without blocking:
AsyncFiles
.readAll(path)
.thenAccept(body -> /* invoked on completion */)
.exceptionally(excep -> /* invoked on error*/
You may run the unit tests of RxIo and place a breakpoint at open() and inspect the implementation of WindowsAsynchronousFileChannelImpl.
Until some time ago there were problems with asynchronous file I/O on Linux. There was an aio interface, but it was only asynchronous for O_DIRECT, which is quite inconvenient for standard use cases. So the standard JDK implementation of AsynchronousFileChannel for Linux internally uses thread pooling and simple blocking I/O which is not really asynchronous I/O.
Things have changed a bit since Linux introduced the io_uring interface. It is now possible to use real non-blocking file I/O not just for O_DIRECT but for buffered I/O too. And a lot more, to reduce overhead of syscall and increase performance. Read more about io_uring.
At the moment there is no built-in support for io_uring in Java. There have been rumors that support may appear for better project Loom support, but that's just a rumors.
There are third party libraries that add asynchronous file I/O support via io_uring for Java - jasyncfio.

Java8 Non-blocking IO against spawned process

I would like to spawn an external process from Java and read its output without blocking the reader thread ("Non-blocking IO").
I know the (Socket) Java NIO Selector concept and the brilliant NuProcess library, but I am wondering, isn't there any built-in solution for that in Java8?
If you want non-blocking IO for consuming the output of an external process and you don't want to include a third party dependency, you you still have to write additional threading code and e.g. use BlockingQueue to pass around data read -- is that really all we have got?

Why should I use NIO (or frameworks like netty) instead of java executors?

Just recently, I learnt about NIO. What I understood is that the main advantage of NIO is we can handle many connections with only one (or few) threads thanks to non-blocking feature of NIO. But can't we achieve this goal using Executors and having a list of worker threads?
I cannot see any advantage of NIO over Executors. Instead, I think executors are better than using NIO as reading messages is very easy and we only need call readLin() for example, but in NIO we should check if the message is partial or the buffer has several messages.
The feature of non-blocking exists in the soul of executors too, where we call execute function of an executor, we are basically add the connection to a buffer and waiting for the fixed number of thread to be free.
So, why would someone use NIO instead of using executors?
Thanks
Multi-threading is as fast as(or even faster than) NIO until you encounter the scalability issue. Too many threads makes the performance lower than NIO.
But in some cases it was said that multi-threading blocking IO is still better than NIO:http://paultyma.blogspot.com/2008/03/writing-java-multithreaded-servers.html

Should I use java.io or java.nio for my network client implementation?

So I'm creating a game, very basic multiplayer. I've got the server side down using asynchronous non-blocking I/O (raw java.nio) but now I need to design the client.
I'm not sure how I should do this. My gut tells me using NIO for a client is overkill (it's not like it's going to handle multiple connections, right?) but I want a second opinion.
So the question is, for a single-connection client, is the best option to use java.io, or java.nio?
And, if the best option is standard I/O, is it still good practice to use ByteBuffers? Or just the usual byte arrays?
Performance may vary, but it is platform dependant and most likely insignificant. For example, tests I've done have shown that NIO and standard I/O perform differently on Linux and Windows. When sending large amounts of data, NIO performed better on the Linux platform, but it was the opposite on Windows. Note: I had configured sockets to be blocking on NIO. When writing a client application, there is little reason to be using non-blocking I/O and polling.
I would not worry about performance. It is hard to say which is better in that sense. Go with what you are comfortable with. If you want to use standard I/O, but still would like to use ByteBuffers, what you can do is wrap the InputStream and OutputStream of the Socket using newChannel(InputStream) and newChannel(OutputStream), respectively. However, there is overhead from additional synchronization and other checks. My advice is to use java.nio and use blocking I/O (configureBlocking(true)).
Simple Stream I/O is a lot easier to handle, and not necessarily slower. It internally uses NIO, for the network accesses, too, I think. (Of course, if you can simply reuse your server's code, using it might be an option.)
As OutputStream does not support writing a ByteBuffer, there is no point in using it here.
(Disclaimer: This is just my opinion (and experience from trying to port my stream IO based networking package to NIO). I'm not sure about best practice here.)

java io read and write lock

suppose I have a file that might gets written by one thread/process Writer and read by another thread/process Reader.
Writer updates the file every x time interval, and Reader reads it every y time interval,
if they happen to read and write to the file at the same time, will there be any issues? would the read block until writes finishes? or would the read fails? and vice versa?
What's the best practice here?
You'll need to devise your own locking protocol to implement in the applications. Specifics depend on the underlying operating system, but in general, nothing will stop one process from reading a file even when another process is writing to it.
Java has a FileLock class that can be used to coordinate access to a file. However, you'll need to read the caveats carefully, especially those relating to the system-dependence of this feature. Testing the feature on the target operating system is extremely important.
A key concept of Java's FileLock is that it is only "advisory". Your process should be able to detect that another process holds a lock on a file, but your process can ignore it and do what it likes with the file, no restrictions.
The question is ambiguous whether multiple process will use the file, or merely separate threads within a single Java process. That's a big difference. If the problem requires only thread safety within a single process, a ReentrantReadWriteLock can provide a robust, high performance solution, without any platform-specific pitfalls.
Best practice is to not use a file for communication between processes. File are not designed for this purposes. Instead you should use messaging which IS designed for communication between processes. You can use files as well to audit what has been sent/received,
If you use files alone, you could come up with a solution which is good enough, but I don't believe you will have a solution which could be considered best practice.

Categories