diff --git a/half-sync-half-async/etc/half-sync-half-async.png b/half-sync-half-async/etc/half-sync-half-async.png
new file mode 100644
index 000000000..84658dfde
Binary files /dev/null and b/half-sync-half-async/etc/half-sync-half-async.png differ
diff --git a/half-sync-half-async/etc/half-sync-half-async.ucls b/half-sync-half-async/etc/half-sync-half-async.ucls
new file mode 100644
index 000000000..5b9941872
--- /dev/null
+++ b/half-sync-half-async/etc/half-sync-half-async.ucls
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java
new file mode 100644
index 000000000..77b1988ba
--- /dev/null
+++ b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java
@@ -0,0 +1,118 @@
+package com.iluwatar.halfsynchalfasync;
+
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * This application demonstrates Half-Sync/Half-Async pattern. Key parts of the pattern are
+ * {@link AsyncTask} and {@link AsynchronousService}.
+ *
+ *
+ * PROBLEM
+ *
+ * A concurrent system have a mixture of short duration, mid duration and long duration tasks.
+ * Mid or long duration tasks should be performed asynchronously to meet quality of service
+ * requirements.
+ *
+ *
INTENT
+ *
+ * The intent of this pattern is to separate the the synchronous and asynchronous processing
+ * in the concurrent application by introducing two intercommunicating layers - one for sync
+ * and one for async. This simplifies the programming without unduly affecting the performance.
+ *
+ *
+ * APPLICABILITY
+ *
+ *
+ * - UNIX network subsystems - In operating systems network operations are carried out
+ * asynchronously with help of hardware level interrupts.
+ * - CORBA - At the asynchronous layer one thread is associated with each socket that is
+ * connected to the client. Thread blocks waiting for CORBA requests from the client. On receiving
+ * request it is inserted in the queuing layer which is then picked up by synchronous layer which
+ * processes the request and sends response back to the client.
+ * - Android AsyncTask framework - Framework provides a way to execute long running blocking calls,
+ * such as downloading a file, in background threads so that the UI thread remains free to respond
+ * to user inputs.
+ *
+ *
+ *
+ * IMPLEMENTATION
+ *
+ * The main method creates an asynchronous service which does not block the main thread while
+ * the task is being performed. The main thread continues its work which is similar to Async Method
+ * Invocation pattern. The difference between them is that there is a queuing layer between Asynchronous
+ * layer and synchronous layer, which allows for different communication patterns between both layers.
+ * Such as Priority Queue can be used as queuing layer to prioritize the way tasks are executed.
+ * Our implementation is just one simple way of implementing this pattern, there are many variants possible
+ * as described in its applications.
+ */
+public class App {
+
+ public static void main(String[] args) {
+ AsynchronousService service = new AsynchronousService(new LinkedBlockingQueue<>());
+ /*
+ * A new task to calculate sum is received but as this is main thread, it should not block.
+ * So it passes it to the asynchronous task layer to compute and proceeds with handling other
+ * incoming requests. This is particularly useful when main thread is waiting on Socket to receive
+ * new incoming requests and does not wait for particular request to be completed before responding
+ * to new request.
+ */
+ service.execute(new ArithmeticSumTask(1000));
+
+ /* New task received, lets pass that to async layer for computation. So both requests will be
+ * executed in parallel.
+ */
+ service.execute(new ArithmeticSumTask(500));
+ service.execute(new ArithmeticSumTask(2000));
+ service.execute(new ArithmeticSumTask(1));
+ }
+
+ static class ArithmeticSumTask implements AsyncTask {
+ private long n;
+
+ public ArithmeticSumTask(long n) {
+ this.n = n;
+ }
+
+ /*
+ * This is the long running task that is performed in background. In our example
+ * the long running task is calculating arithmetic sum with artificial delay.
+ */
+ @Override
+ public Long call() throws Exception {
+ return ap(n);
+ }
+
+ /*
+ * This will be called in context of the main thread where some validations can be
+ * done regarding the inputs. Such as it must be greater than 0. It's a small
+ * computation which can be performed in main thread. If we did validated the input
+ * in background thread then we pay the cost of context switching
+ * which is much more than validating it in main thread.
+ */
+ @Override
+ public void onPreCall() {
+ if (n < 0) {
+ throw new IllegalArgumentException("n is less than 0");
+ }
+ }
+
+ @Override
+ public void onPostCall(Long result) {
+ // Handle the result of computation
+ System.out.println(result);
+ }
+
+ @Override
+ public void onError(Throwable throwable) {
+ throw new IllegalStateException("Should not occur");
+ }
+ }
+
+ private static long ap(long i) {
+ try {
+ Thread.sleep(i);
+ } catch (InterruptedException e) {
+ }
+ return (i) * (i + 1) / 2;
+ }
+}
diff --git a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsyncTask.java b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsyncTask.java
index d773ff93f..8ed7376b6 100644
--- a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsyncTask.java
+++ b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsyncTask.java
@@ -13,20 +13,23 @@ import java.util.concurrent.Callable;
public interface AsyncTask extends Callable {
/**
* Is called in context of caller thread before call to {@link #call()}. Large
- * tasks should not be performed in this method. Validations can be performed here
- * so that the performance penalty of context switching is not incurred in case of
- * invalid requests.
+ * tasks should not be performed in this method as it will block the caller thread.
+ * Small tasks such as validations can be performed here so that the performance penalty
+ * of context switching is not incurred in case of invalid requests.
*/
- void preExecute();
+ void onPreCall();
/**
- * A callback called after the result is successfully computed by {@link #call()}.
+ * A callback called after the result is successfully computed by {@link #call()}. In our
+ * implementation this method is called in context of background thread but in some variants,
+ * such as Android where only UI thread can change the state of UI widgets, this method is called
+ * in context of UI thread.
*/
- void onResult(O result);
+ void onPostCall(O result);
/**
* A callback called if computing the task resulted in some exception. This method
- * is called when either of {@link #call()} or {@link #preExecute()} throw any exception.
+ * is called when either of {@link #call()} or {@link #onPreCall()} throw any exception.
*
* @param throwable error cause
*/
diff --git a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java
index 8b858747e..6c36354d0 100644
--- a/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java
+++ b/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java
@@ -38,18 +38,16 @@ public class AsynchronousService {
* A non-blocking method which performs the task provided in background and returns immediately.
*
* On successful completion of task the result is posted back using callback method
- * {@link AsyncTask#onResult(Object)}, if task execution is unable to complete normally
+ * {@link AsyncTask#onPostCall(Object)}, if task execution is unable to complete normally
* due to some exception then the reason for error is posted back using callback method
* {@link AsyncTask#onError(Throwable)}.
*
* NOTE: The results are posted back in the context of background thread in this implementation.
- * There is other variant possible where the result is posted back in the queue of caller thread
- * and then the result is processed in context of caller thread.
*/
public void execute(final AsyncTask task) {
try {
// some small tasks such as validation can be performed here.
- task.preExecute();
+ task.onPreCall();
} catch (Exception e) {
task.onError(e);
}
@@ -65,7 +63,7 @@ public class AsynchronousService {
* where the UI elements can only be updated using UI thread. So result must be
* posted back in UI thread.
*/
- task.onResult(get());
+ task.onPostCall(get());
} catch (InterruptedException e) {
// should not occur
} catch (ExecutionException e) {