event-based-asynchronous/README.md
The Event-Based Asynchronous pattern allows a system to handle tasks that might take some time to complete without blocking the execution of the program. It enables better resource utilization by freeing up a thread that would otherwise be blocked waiting for the task to complete.
Real-world example
A real-world analogy of the Event-Based Asynchronous design pattern is how a restaurant operates. When a customer places an order, the waiter records the order and passes it to the kitchen. Instead of waiting at the kitchen for the food to be prepared, the waiter continues to serve other tables. Once the kitchen completes the order, they signal (event) the waiter, who then delivers the food to the customer. This allows the waiter to handle multiple tasks efficiently without idle waiting, similar to how asynchronous programming handles tasks in parallel, enhancing overall efficiency and responsiveness.
In Plain Words
The Event-Based Asynchronous design pattern allows tasks to be executed in the background, notifying the main program via events when completed, thereby enhancing system efficiency and responsiveness without blocking ongoing operations.
Sequence diagram
Event-Based Asynchronous design pattern allows tasks to be executed in the background, notifying the main program via events when completed, thereby enhancing system efficiency and responsiveness without blocking ongoing operations.
In the provided code, we have several key classes implementing this pattern:
App: The main class that runs the application. It interacts with the EventManager to create, start, stop, and check the status of events.EventManager: Manages the lifecycle of events, including creating, starting, stopping, and checking the status of events. It maintains a map of event IDs to Event objects.Event: An abstract class that represents an event. It has two concrete subclasses: AsyncEvent and SyncEvent.AsyncEvent and SyncEvent: Represent asynchronous and synchronous events respectively.EventManager when certain conditions are not met.Here's a simplified code example of how these classes interact:
// Create an EventManager
EventManager eventManager = new EventManager();
// Create an asynchronous event that runs for 60 seconds
int asyncEventId = eventManager.createAsync(Duration.ofSeconds(60));
// Start the asynchronous event
eventManager.start(asyncEventId);
// Check the status of the asynchronous event
eventManager.status(asyncEventId);
// Stop the asynchronous event
eventManager.cancel(asyncEventId);
In this example, the App class creates an EventManager, then uses it to create, start, check the status of, and stop an asynchronous event. The EventManager creates an AsyncEvent object, starts it in a separate thread, checks its status, and stops it when requested.
The EventManager class is the core of the Event-Based Asynchronous pattern implementation. It manages the lifecycle of events, including creating, starting, stopping, and checking the status of events. It maintains a map of event IDs to Event objects. Here's a snippet of how it creates an asynchronous event:
public int createAsync(Duration runtime) throws MaxNumOfEventsAllowedException, LongRunningEventException {
int id = counter.incrementAndGet();
events.put(id, new AsyncEvent(id, runtime));
return id;
}
The Event class is an abstract class that represents an event. It has two concrete subclasses: AsyncEvent and SyncEvent. An Event has an ID, a runtime (how long it should run), and a status (whether it's running, completed, or ready to start). It also has methods to start and stop the event. Here's a snippet of how an AsyncEvent starts:
@Override
public void start() {
Thread thread = new Thread(() -> {
try {
handleRunStart();
Thread.sleep(getRuntime().toMillis());
handleRunComplete();
} catch (InterruptedException e) {
handleRunFailure(e.getMessage());
}
});
thread.start();
}
In this snippet, when an AsyncEvent is started, it runs in a separate thread without blocking the main thread.
A synchronous event is created and managed similarly to an asynchronous event. Here's a snippet of how it creates and manages a synchronous event:
// Create an EventManager
EventManager eventManager = new EventManager();
// Create a synchronous event that runs for 60 seconds
int syncEventId = eventManager.create(Duration.ofSeconds(60));
// Start the synchronous event
eventManager.start(syncEventId);
// Check the status of the synchronous event
eventManager.status(syncEventId);
// Stop the synchronous event
eventManager.cancel(syncEventId);
In the EventManager class, a synchronous event is created using the create method:
public int create(Duration runtime) throws MaxNumOfEventsAllowedException, LongRunningEventException {
int id = counter.incrementAndGet();
events.put(id, new SyncEvent(id, runtime));
return id;
}
The SyncEvent class is a subclass of Event that represents a synchronous event. When a SyncEvent is started, it runs on the main thread and blocks it until the event is completed. Here's a snippet of how a SyncEvent starts:
@Override
public void start() {
try {
handleRunStart();
Thread.sleep(getRuntime().toMillis());
handleRunComplete();
} catch (InterruptedException e) {
handleRunFailure(e.getMessage());
}
}
In this snippet, when a SyncEvent is started, it runs on the main thread, blocking it until the event is completed. This is in contrast to an AsyncEvent, which runs in a separate thread without blocking the main thread.
These are the key parts of the Event-Based Asynchronous design pattern as implemented in this code. The pattern allows tasks to be executed in the background, notifying the main program via events when completed, thereby enhancing system efficiency and responsiveness without blocking ongoing operations.
Benefits:
Trade-offs: