program tip

비 차단 IO 대 비동기 IO 및 Java 구현

radiobox 2020. 11. 30. 08:00
반응형

비 차단 IO 대 비동기 IO 및 Java 구현


이 두 개념의 차이점을 직접 요약하려고합니다 (사람들이 두 개념을 한 문장으로 사용하는 것을 볼 때 정말 혼란 스럽습니다. 예를 들어 "non-blocking async IO"가 무엇인지 알아 내려고합니다. 평균).

따라서 내 이해에서 비 차단 IO는 데이터가 준비된 경우 IO를 처리하는 기본 OS 메커니즘입니다. 그렇지 않으면 오류를 반환하거나 아무것도하지 않습니다.

비동기 IO에서는 콜백 만 제공하면 데이터를 사용할 수있을 때 애플리케이션에 알림이 전송됩니다.

그렇다면 실제로 "비 차단 비동기 IO"는 무엇입니까? 그들 모두가 자바로 구현 될 수 있는지 그리고 (외부 libs가없이 표준 JDK, 나는 거기에 알 java.nio.channels.{Channels, Selector, SelectorKey}java.nio.channels.{AsynchronousSocketChannel}) : IO 비동기, IO 비 차단하고, IO 비동기 (같은 것은있을 경우) 비 차단?


그렇다면 실제로 "비 차단 비동기 IO"는 무엇입니까?

이에 답하려면 먼저 비동기 I / O차단하는 것과 같은 것이 없다는 것을 이해해야합니다 . 비동기의 바로 그 개념은 대기, 차단, 지연이 없음을 나타냅니다. 당신이 볼 때 비 차단 비동기 I / O를비는 차단 비트 만 더 자격을하는 역할을 비동기 용어의 형용사. 따라서 효과적으로 비 차단 비동기 I / O 는 약간의 중복이 될 수 있습니다.

주로 두 종류의 I / O가 있습니다. 동기비동기 . Synchronous는 처리가 완료 될 때까지 현재 실행 스레드를 차단하는 반면 Asynchronous는 현재 실행 스레드를 차단하지 않고 추가 처리를 위해 OS 커널에 제어를 전달합니다. 그런 다음 커널은 제출 된 작업이 완료되면 비동기 스레드에 알립니다.


비동기 채널 그룹

Java의 비동기 채널 개념은 비동기 채널 그룹에 의해 뒷받침됩니다. 비동기 채널 그룹은 기본적으로 재사용을 위해 여러 채널을 풀링합니다. 비동기 API의 소비자는 그룹에서 채널을 검색하고 (JVM은 기본적으로 하나를 생성 함) 채널은 읽기 / 쓰기 작업이 완료된 후 자동으로 그룹에 다시 배치됩니다. 궁극적으로 비동기 채널 그룹은 놀라운 스레드 풀의 지원을받습니다 . 또한 비동기 채널은 스레드로부터 안전합니다.

비동기 채널 그룹을 지원하는 스레드 풀의 크기는 다음 JVM 속성으로 구성됩니다.

java.nio.channels.DefaultThreadPool.initialSize

정수 값이 주어지면 해당 크기의 스레드 풀을 설정하여 채널 그룹을 지원합니다. 채널 그룹은 생성되고 개발자에게 투명하게 유지됩니다.


그리고 그것들을 모두 자바로 구현하는 방법

글쎄요, 당신이 물어서 기쁩니다. 다음은 AsynchronousSocketChannel(비 차단 클라이언트 Socket를 리스닝 서버 에 여는 데 사용되는 ) 예제입니다.이 샘플은 Apress Pro Java NIO.2 에서 발췌 한 것입니다.

//Create an Asynchronous channel. No connection has actually been established yet
AsynchronousSocketChannel asynchronousSocketChannel = AsynchronousSocketChannel.open(); 

/**Connect to an actual server on the given port and address. 
   The operation returns a type of Future, the basis of the all 
   asynchronous operations in java. In this case, a Void is 
   returned because nothing is returned after a successful socket connection
  */
Void connect = asynchronousSocketChannel.connect(new InetSocketAddress("127.0.0.1", 5000)).get();


//Allocate data structures to use to communicate over the wire
ByteBuffer helloBuffer = ByteBuffer.wrap("Hello !".getBytes()); 

//Send the message

Future<Integer> successfullyWritten=  asynchronousSocketChannel.write(helloBuffer);

//Do some stuff here. The point here is that asynchronousSocketChannel.write() 
//returns almost immediately, not waiting to actually finish writing 
//the hello to the channel before returning control to the currently executing thread

doSomethingElse();

//now you can come back and check if it was all written (or not)

System.out.println("Bytes written "+successfullyWritten.get());

편집 : Async NIO에 대한 지원이 JDK 1.7에서 제공되었음을 언급해야합니다.


나는 이것이 오래된 질문이라고 생각하지만 @nickdu가 지적하려고 시도했지만 명확하지 않은 무언가가 누락되었다고 생각합니다.

이 토론과 관련된 4 가지 유형의 IO가 있습니다.

IO 차단

비 차단 IO

비동기 IO

비동기식 비 차단 IO

모호한 정의 때문에 혼란이 발생합니다. 그래서 그것을 명확히 해보도록하겠습니다.

먼저 IO에 대해 이야기합시다. 느린 IO가있을 때 이것은 가장 분명하지만 IO 작업은 차단되거나 차단되지 않을 수 있습니다. 이것은 스레드와 관련이 없으며 운영 체제에 대한 인터페이스와 관련이 있습니다. OS에 IO 작업을 요청할 때 모든 데이터가 준비 될 때까지 기다리 거나 ( blocking ) 지금 사용할 수 있는 데이터를 가져 와서 계속 진행할 ( 비 차단). 기본값은 IO 차단입니다. 경로가 훨씬 명확하기 때문에 차단 IO를 사용하여 코드를 작성하는 것이 훨씬 쉽습니다. 그러나 코드를 중지하고 IO가 완료 될 때까지 기다려야합니다. 비 차단 IO는 편리한 작업을 제공하는 상위 수준 라이브러리 대신 선택 및 읽기 / 쓰기를 사용하여 하위 수준에서 IO 라이브러리와 인터페이스해야합니다. 비 차단 IO는 OS가 IO를 수행하는 동안 작업해야 할 작업이 있음을 의미합니다. 이는 여러 IO 작업 또는 완료된 IO에 대한 계산 일 수 있습니다.

Blocking IO - The application waits for the OS to gather all the bytes to complete the operation or reach the end before continuing. This is default. To be more clear for the very technical, the system call that initiates the IO will install a signal handler waiting for a processor interrupt that will occur when the IO operation makes progress. Then the system call will begin a sleep which suspends operation of the current process for a period of time, or until the process interrupt occurs.

Non-Blocking IO - The application tells the OS it only wants what bytes are available right now, and moves on while the OS concurrently gathers more bytes. The code uses select to determine what IO operations have bytes available. In this case the system call will again install a signal handler, but rather than sleep, it will associate the signal handler with the file handle, and immediately return. The process will become responsible for periodically checking the file handle for the interrupt flag having been set. This is usually done with a select call.

Now Asynchronous is where the confusion begins. The general concept of asynchronous only implies that the process continues while the background operation is performed, the mechanism by which this occurs is not specific. The term is ambiguous as both non-blocking IO and threaded blocking IO can be considered to be asynchronous. Both allow concurrent operations, however the resource requirements are different, and the code is substantially different. Because you have asked a question "What is Non-Blocking Asynchronous IO", I am going to use a stricter definition for asynchronous, a threaded system performing IO which may or may not be non-blocking.

The general definition

Asynchronous IO - Programmatic IO which allows multiple concurrent IO operations to occur. IO operations are happening simultaneously, so that code is not waiting for data that is not ready.

The stricter definition

Asynchronous IO - Programmatic IO which uses threading or multiprocessing to allow concurrent IO operations to occur.

Now with those clearer definitions we have the following four types of IO paradigms.

Blocking IO - Standard single threaded IO in which the application waits for all IO operations to complete before moving on. Easy to code, no concurrency and so slow for applications that require multiple IO operations. The process or thread will sleep while waiting for the IO interrupt to occur.

Asynchronous IO - Threaded IO in which the application uses threads of execution to perform Blocking IO operations concurrently. Requires thread safe code, but is generally easier to read and write than the alternative. Gains the overhead of multiple threads, but has clear execution paths. May require the use of synchronized methods and containers.

Non-Blocking IO - Single threaded IO in which the application uses select to determine which IO operations are ready to advance, allowing the execution of other code or other IO operations while the OS processes concurrent IO. The process does not sleep while waiting for the IO interrupt, but takes on the responsibility to check for the IO flag on the filehandle. Much more complicated code due to the need to check the IO flag with select, though does not require thread-safe code or synchronized methods and containers. Low execution over-head at the expense of code complexity. Execution paths are convoluted.

Asynchronous Non-Blocking IO - A hybrid approach to IO aimed at reducing complexity by using threads, while maintaining scalability by using non-blocking IO operations where possible. This would be the most complex type of IO requiring synchronized methods and containers, as well as convoluted execution paths. This is not the type of IO that one should consider coding lightly, and is most often only used when using a library that will mask the complexity, something like Futures and Promises.


I would say there are three types of io:

synchronous blocking
synchronous non-blocking
asynchronous

Both synchronous non-blocking and asynchronous would be considered non-blocking as the calling thread is not waiting on the IO to complete. So while non-blocking asynchronous io might be redundant, they are not one in the same. When I open a file I can open it in non-blocking mode. What does this mean? It means when I issue a read() it won't block. It will either return me the bytes that are available or indicate that there are no bytes available. If I didn't enable non-blocking io the read() would block until data was available. I might want to enable non-blocking io if I want a thread to handle multiple io requests. For instance, I could use select() to find out what file descriptors, or maybe sockets, have data available to read. I then do synchronous reads on those file descriptors. None of those reads should block because I already know data is available, plus I have opened the file descriptors in non-blocking mode.

Asynchronous io is where you issue an io request. That request is queued, and thus doesn't block the issuing thread. You are notified when either the request failed or has completed successfully.


Non blocking IO is when the call to perform IO returns immediately, and does not block your thread.

The only way to know if the IO is done, is to poll its status or block. Think of it as a Future. You start an IO operation, and it returns you a Future. You can call isDone() on it to check if its done, if it is, do what you want with it, otherwise keep doing other stuff until the next time you want to check if its done. Or, if you're out of things to do, you can call get on it, which will block until its done.

Async IO is when the call to perform IO notifies you it is done through an event, not through its return value.

This can be blocking or non-blocking.

Blocking Async IO

What is meant by blocking async IO is that the call to perform IO is a normal blocking call, but the thing you called wrapped that call inside a thread which will block until the IO is done and then delegate the handling of the result of the IO to your callback. That is, there is still a thread lower down the stack which is blocked on the IO, but your thread isn't.

Non-blocking Async IO

This is actually the more common one, and it means that the non-blocking IO does not need to be polled for its status, as with standard non-blocking IO, instead it will call your callback when its done. As opposed to blocking async IO, this one has no threads blocked anywhere down the stack, thus its faster and uses less resources, as the asynchronous behavior is managed without blocking threads.

You can think of it as a CompletableFuture. It requires that your program has some form of async event framework, which can be multi-threaded or not. So its possible the callback is executed in another thread, or that it is scheduled for execution on an existing thread once the current task is done.

I explain the distinction more thoroughly here.

참고URL : https://stackoverflow.com/questions/25099640/non-blocking-io-vs-async-io-and-implementation-in-java

반응형