Java8 Non-blocking IO against spawned process - java

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?

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.

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

Can I use two sockets in single thread?

I am having trouble developing a chat application including file sharing. It's a server and client based desktop application. I am able to develop chat and also file sharing individually.
Now I want merge two project and having problem. Is it possible to use multiple socket in single thread like main thread? Or do I have to use one for chatting and another for file sharing?
I think that is possible but in the same thread one operation with one socket have to wait all the operations from annother finish. if you want the two operations execute at the same time do it in different threads.
Hope that helps :)
Yes it is possible for a single thread to use multiple sockets. See the Selector API.
The basic idea is that the code in your thread needs to know about all of the selectable channels (sockets, open files, etc) that it needs to read from or write to. It registers the channels with the selector. Then you make a select call which will (for example) block until one of the registered channels is ready; e.g. a socket that has data that can be read now ... without blocking.
It is complicated, but rather than explaining it all here, I suggest that you read Baeldung's Introduction to the Java NIO Selector which includes an example.
But the bottom line is that using Selector will probably entail significant restructuring of your existing code. And if your code is using (for example) a 3rd-party library to do the I/O, then this approach probably won't work. Using multiple threads may well be a simpler option.

Assigning a core to TCP polling

We have several Java applications that run on the same Linux machine and send messages back and forth via TCP. We use a ServerSocket and Socket to create the connections. I want to reduce the latency of this communication as much as possible. It seems to be possible to assign a core on our box to do continuous TCP polling which will improve that performance. How is that done in Linux and / or Java?
There is a way to achieve this, but it is not be portable.
What you need to do is:
1) Find out native thread id
2) Set affinity for the native thread
You can get the native thread id (which on linux is a process id) using unsupported classes from packages under sun.jvm.hotspot. You can link against these classes by including sa-jdi.jar (bundled with the jdk) to build path. Since I don't like idea of copying the answer from another site, you should go and read the instructions from github
Once you have obtained the native thread id, you should use 'taskset' command line utility to change the affinity. You can find the instructions how to use taskset from another post
It isn't. There is no way to assign a thread to a core in Java.
And assigning a single core won't improve the performance; on the contrary it will probably reduce it. I don't know exactly what you mean by 'polling' but you can't do it with Sockets: you have to use separate threads blocking in read(). If you are contemplating using InputStream.available() you are barking up the wrong tree altogether and should be using NIO with a Selector.

Why FileChannel in Java is not non-blocking?

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.

Categories