Changed method names and did proper documentation
This commit is contained in:
		
							
								
								
									
										
											BIN
										
									
								
								half-sync-half-async/etc/half-sync-half-async.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								half-sync-half-async/etc/half-sync-half-async.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 32 KiB | 
							
								
								
									
										77
									
								
								half-sync-half-async/etc/half-sync-half-async.ucls
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								half-sync-half-async/etc/half-sync-half-async.ucls
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"  | ||||||
|  |   realizations="true" associations="true" dependencies="false" nesting-relationships="true">   | ||||||
|  |   <class id="1" language="java" name="com.iluwatar.halfsynchalfasync.AsynchronousService" project="half-sync-half-async"  | ||||||
|  |     file="/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java" binary="false"  | ||||||
|  |     corner="BOTTOM_RIGHT">     | ||||||
|  |     <position height="115" width="265" x="41" y="37"/>     | ||||||
|  |     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||||
|  |       sort-features="false" accessors="true" visibility="true">       | ||||||
|  |       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||||
|  |       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||||
|  |     </display>   | ||||||
|  |   </class>   | ||||||
|  |   <interface id="2" language="java" name="com.iluwatar.halfsynchalfasync.AsyncTask" project="half-sync-half-async"  | ||||||
|  |     file="/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsyncTask.java" binary="false"  | ||||||
|  |     corner="BOTTOM_RIGHT">     | ||||||
|  |     <position height="-1" width="-1" x="776" y="223"/>     | ||||||
|  |     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||||
|  |       sort-features="false" accessors="true" visibility="true">       | ||||||
|  |       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||||
|  |       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||||
|  |     </display>   | ||||||
|  |   </interface>   | ||||||
|  |   <interface id="3" language="java" name="java.util.concurrent.BlockingQueue" project="async-method-invocation"  | ||||||
|  |     file="/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">     | ||||||
|  |     <position height="-1" width="-1" x="494" y="310"/>     | ||||||
|  |     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||||
|  |       sort-features="false" accessors="true" visibility="true">       | ||||||
|  |       <attributes public="false" package="false" protected="false" private="false" static="true"/>       | ||||||
|  |       <operations public="false" package="false" protected="false" private="false" static="true"/>     | ||||||
|  |     </display>   | ||||||
|  |   </interface>   | ||||||
|  |   <class id="4" language="java" name="java.util.concurrent.ThreadPoolExecutor" project="async-method-invocation"  | ||||||
|  |     file="/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">     | ||||||
|  |     <position height="-1" width="-1" x="174" y="343"/>     | ||||||
|  |     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||||
|  |       sort-features="false" accessors="true" visibility="true">       | ||||||
|  |       <attributes public="true" package="true" protected="true" private="false" static="true"/>       | ||||||
|  |       <operations public="false" package="false" protected="false" private="false" static="false"/>     | ||||||
|  |     </display>   | ||||||
|  |   </class>   | ||||||
|  |   <interface id="5" language="java" name="java.util.concurrent.Callable" project="async-method-invocation"  | ||||||
|  |     file="/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">     | ||||||
|  |     <position height="-1" width="-1" x="772" y="47"/>     | ||||||
|  |     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||||
|  |       sort-features="false" accessors="true" visibility="true">       | ||||||
|  |       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||||
|  |       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||||
|  |     </display>   | ||||||
|  |   </interface>   | ||||||
|  |   <generalization id="6">     | ||||||
|  |     <end type="SOURCE" refId="2"/>     | ||||||
|  |     <end type="TARGET" refId="5"/>   | ||||||
|  |   </generalization>   | ||||||
|  |   <association id="7">     | ||||||
|  |     <end type="SOURCE" refId="4" navigable="false">       | ||||||
|  |       <attribute id="8" name="workQueue"/>       | ||||||
|  |       <multiplicity id="9" minimum="0" maximum="1"/>     | ||||||
|  |     </end>     | ||||||
|  |     <end type="TARGET" refId="3" navigable="true"/>     | ||||||
|  |     <display labels="true" multiplicity="true"/>   | ||||||
|  |   </association>   | ||||||
|  |   <dependency id="10">     | ||||||
|  |     <end type="SOURCE" refId="1"/>     | ||||||
|  |     <end type="TARGET" refId="3"/>   | ||||||
|  |   </dependency>   | ||||||
|  |   <dependency id="11">     | ||||||
|  |     <end type="SOURCE" refId="1"/>     | ||||||
|  |     <end type="TARGET" refId="4"/>   | ||||||
|  |   </dependency>   | ||||||
|  |   <classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||||
|  |     sort-features="false" accessors="true" visibility="true">     | ||||||
|  |     <attributes public="true" package="true" protected="true" private="true" static="true"/>     | ||||||
|  |     <operations public="true" package="true" protected="true" private="true" static="true"/>   | ||||||
|  |   </classifier-display>   | ||||||
|  |   <association-display labels="true" multiplicity="true"/> | ||||||
|  | </class-diagram> | ||||||
| @@ -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}. | ||||||
|  |  *  | ||||||
|  |  * <p> | ||||||
|  |  * <i>PROBLEM</i> | ||||||
|  |  * <br/> | ||||||
|  |  * 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. | ||||||
|  |  *    | ||||||
|  |  * <p><i>INTENT</i> | ||||||
|  |  * <br/> | ||||||
|  |  * 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. | ||||||
|  |  *   | ||||||
|  |  * <p> | ||||||
|  |  * <i>APPLICABILITY</i> | ||||||
|  |  * <br/> | ||||||
|  |  * <ul> | ||||||
|  |  * <li>UNIX network subsystems - In operating systems network operations are carried out | ||||||
|  |  * asynchronously with help of hardware level interrupts.</li> | ||||||
|  |  * <li>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.</li> | ||||||
|  |  * <li>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.</i> | ||||||
|  |  *  </ul> | ||||||
|  |  *   | ||||||
|  |  * <p> | ||||||
|  |  * <i>IMPLEMENTATION</i> | ||||||
|  |  * <br/> | ||||||
|  |  * 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<Long> { | ||||||
|  | 		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; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -13,20 +13,23 @@ import java.util.concurrent.Callable; | |||||||
| public interface AsyncTask<O> extends Callable<O> { | public interface AsyncTask<O> extends Callable<O> { | ||||||
| 	/** | 	/** | ||||||
| 	 * Is called in context of caller thread before call to {@link #call()}. Large | 	 * 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 | 	 * tasks should not be performed in this method as it will block the caller thread. | ||||||
| 	 * so that the performance penalty of context switching is not incurred in case of | 	 * Small tasks such as validations can be performed here so that the performance penalty | ||||||
| 	 * invalid requests. | 	 * 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 | 	 * 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 | 	 * @param throwable error cause | ||||||
| 	 */ | 	 */ | ||||||
|   | |||||||
| @@ -38,18 +38,16 @@ public class AsynchronousService { | |||||||
| 	 * A non-blocking method which performs the task provided in background and returns immediately. | 	 * A non-blocking method which performs the task provided in background and returns immediately. | ||||||
| 	 * <p> | 	 * <p> | ||||||
| 	 * On successful completion of task the result is posted back using callback method | 	 * 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 | 	 * due to some exception then the reason for error is posted back using callback method | ||||||
| 	 * {@link AsyncTask#onError(Throwable)}. | 	 * {@link AsyncTask#onError(Throwable)}. | ||||||
| 	 * <p> | 	 * <p> | ||||||
| 	 * NOTE: The results are posted back in the context of background thread in this implementation. | 	 * 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 <T> void execute(final AsyncTask<T> task) { | 	public <T> void execute(final AsyncTask<T> task) { | ||||||
| 		try { | 		try { | ||||||
| 			// some small tasks such as validation can be performed here. | 			// some small tasks such as validation can be performed here. | ||||||
| 			task.preExecute(); | 			task.onPreCall(); | ||||||
| 		} catch (Exception e) { | 		} catch (Exception e) { | ||||||
| 			task.onError(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 | 					 * where the UI elements can only be updated using UI thread. So result must be | ||||||
| 					 * posted back in UI thread. | 					 * posted back in UI thread. | ||||||
| 					 */ | 					 */ | ||||||
| 					task.onResult(get()); | 					task.onPostCall(get()); | ||||||
| 				} catch (InterruptedException e) { | 				} catch (InterruptedException e) { | ||||||
| 					// should not occur | 					// should not occur | ||||||
| 				} catch (ExecutionException e) { | 				} catch (ExecutionException e) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user