When describing I/O, the terms non-blocking and asynchronous are often used interchangeably, but there is a significant difference between them. In this article are described the theoretical and practical differences between non-blocking and asynchronous sockets I/O operations in Java.
Sockets are endpoints to perform two-way communication by TCP and UDP protocols. Java sockets APIs are adapters for the corresponding functionality of the operating systems. Sockets communication in POSIX-compliant operating systems (Unix, Linux, Mac OS X, BSD, Solaris, AIX, etc.) is performed by Berkeley sockets. …
The CompletableFuture API is a high-level API for asynchronous programming in Java. This API supports pipelining (also known as chaining or combining) of multiple asynchronous computations into a single result without the mess of nested callbacks (“callback hell“). This API also is an implementation of the future/promise concurrency constructs in Java.
Since Java 5 there is a much simpler API for asynchronous programming: the Future interface and its base implementation, the FutureTask class. The Future interface represents the result of asynchronous computation and has only a few methods:
The WebSocket protocol is designed to overcome the architecture limitations of HTTP-based solutions in simultaneous bi-directional communication. Most importantly, WebSocket has another communication model (simultaneous bi-directional messaging) than HTTP (request-response).
WebSocket works over TCP that allows transmitting of two-way streams of bytes. WebSocket provides thin functionality on top of TCP that allows transmitting binary and text messages providing necessary security constraints of the Web. But WebSocket does not specify the format of such messages.
WebSocket is intentionally designed to be as simple as possible. To avoid additional protocol complexity, clients and servers are intended to use subprotocols on top of…
According to some sources, the WebSocket API is currently (2020) implemented in the most common browsers:
The HTTP protocol is a request-response protocol. That means that only a client can send HTTP requests to a server. A server can only service HTTP requests by sending back HTTP responses, but a server can not send unrequested HTTP responses to a client.
This is because HTTP was originally designed for request-response resources transfer in distributed hypermedia systems but not for simultaneous bi-directional communication. To overcome these architecture limitations are used several HTTP mechanisms (grouped under the unofficial name Comet) that are often complicated and inefficient.
The WebSocket protocol is designed to replace existing workaround HTTP mechanisms and provide…
Barrier synchronizers (barriers) are a kind of synchronizer that ensures that any threads must stop at a certain point and can’t proceed further until all other threads reach this point.
By purpose, barriers can be grouped into the following categories:
Barriers also can be grouped by the number of iterations (one-shot or cyclic) and by the number of parties/threads (fixed or variable).
In Java 7+ there are 3 predefined barrier classes: CountDownLatch, CyclicBarrier, Phaser.
The CountDownLatch class is a one-shot barrier that…
There are no simple, general-purpose methods to implement asynchronous server-to-client communication in web applications with acceptable performance.
HTTP is a request-response protocol in the client-server computing model. To start an exchange, a client submits a request to a server. To finish the exchange, the server returns a response to the client. The server can send a response to only one client — the one that made the request. In the HTTP protocol, a client is the initiator of messages exchange.
There are cases when a server should be the initiator of exchange. One of the methods to implement this is…
In small applications to execute each task (Runnable object) is created a new thread (Thread object). When the task is completed, the thread is terminated as well. But in large applications overhead of threads creation and termination can be significant. Such overhead can be reduced by reusing the same threads for the execution of many tasks. For that purpose are used executors and thread pools. An executor is a design pattern that provides API for task executions and hides its implementation. A thread pool is one of the executor implementations that uses a pool of threads for task execution.
There are several ways to reduce Stream as a sequence of input elements into a single summary result. One of them is to use implementations of Collector interface with Stream.collect(collector) method. It’s possible to implement this interface explicitly, but it should start with studying its predefined implementations from Collectors class.
There are 44 public static factory methods in Collectors class (up to Java 12) that return predefined implementations of Collector interface. To understand them better, it’s rational to divide them into categories, for example:
Senior Software Engineer