Issue #469: Implementation of Event-based Asynchronous pattern

This commit is contained in:
WSSIA 2016-08-08 23:31:41 +01:00
parent ff23e90c4f
commit 2d99061902
16 changed files with 860 additions and 0 deletions

View File

@ -0,0 +1,28 @@
---
layout: pattern
title: Event-based Asynchronous
folder: event-asynchronous
permalink: /patterns/event-asynchronous/
categories: Other
tags:
- Java
---
## Intent
The Event-based Asynchronous Pattern makes available the advantages of multithreaded applications while hiding many
of the complex issues inherent in multithreaded design. Using a class that supports this pattern can allow you to:-
(1) Perform time-consuming tasks, such as downloads and database operations, "in the background," without interrupting your application.
(2) Execute multiple operations simultaneously, receiving notifications when each completes.
(3) Wait for resources to become available without stopping ("hanging") your application.
(4) Communicate with pending asynchronous operations using the familiar events-and-delegates model.
![alt text](./etc/event-asynchronous.png "Event-based Asynchronous")
## Applicability
Use the Event-based Asynchronous pattern(s) when
* Time-consuming tasks are needed to run in the background without disrupting the current application.
## Credits
* [Event-based Asynchronous Pattern Overview](https://msdn.microsoft.com/en-us/library/wewwczdw%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396)

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<class-diagram version="1.1.10" icons="true" automaticImage="PNG" always-add-relationships="false"
generalizations="true" realizations="true" associations="true" dependencies="false" nesting-relationships="true"
router="FAN">
<class id="1" language="java" name="com.iluwatar.event.asynchronous.App" project="event-asynchronous"
file="/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/App.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="629" y="221"/>
<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="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="2" language="java" name="com.iluwatar.event.asynchronous.Event" project="event-asynchronous"
file="/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/Event.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="195" y="475"/>
<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="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="3" language="java" name="com.iluwatar.event.asynchronous.EventManager" project="event-asynchronous"
file="/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventManager.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="575" y="475"/>
<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="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<interface id="4" language="java" name="com.iluwatar.event.asynchronous.IEvent" project="event-asynchronous"
file="/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/IEvent.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="196" y="197"/>
<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="5" language="java" name="com.iluwatar.event.asynchronous.ThreadCompleteListener"
project="event-asynchronous"
file="/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/ThreadCompleteListener.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="396" y="229"/>
<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>
<class id="6" language="java" name="com.iluwatar.event.asynchronous.EventAsynchronousTest"
project="event-asynchronous"
file="/event-asynchronous/src/test/java/com/iluwatar/event/asynchronous/EventAsynchronousTest.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="924" y="220"/>
<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>
<association id="7">
<bendpoint x="433" y="475"/>
<end type="SOURCE" refId="3" navigable="false">
<attribute id="8" name="eventPool"/>
<multiplicity id="9" minimum="0" maximum="2147483647"/>
</end>
<end type="TARGET" refId="2" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="10">
<end type="SOURCE" refId="2" navigable="false">
<attribute id="11" name="eventListener">
<position height="18" width="74" x="250" y="287"/>
</attribute>
<multiplicity id="12" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="5" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="13">
<end type="SOURCE" refId="6" navigable="false">
<attribute id="14" name="app"/>
<multiplicity id="15" minimum="0" maximum="1">
<position height="16" width="23" x="714" y="226"/>
</multiplicity>
</end>
<end type="TARGET" refId="1" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<realization id="16">
<end type="SOURCE" refId="2"/>
<end type="TARGET" refId="4"/>
</realization>
<realization id="17">
<end type="SOURCE" refId="3"/>
<end type="TARGET" refId="5"/>
</realization>
<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>

View File

@ -0,0 +1,42 @@
<?xml version="1.0"?>
<!--
The MIT License
Copyright (c) 2014 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.13.0-SNAPSHOT</version>
</parent>
<artifactId>event-asynchronous</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,185 @@
/**
* The MIT License Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.iluwatar.event.asynchronous;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Scanner;
/**
*
* This application demonstrates the <b>Event-based Asynchronous</b> pattern. Essentially, users (of the pattern) may
* choose to run events in an Asynchronous or Synchronous mode. There can be multiple Asynchronous events running at
* once but only one Synchronous event can run at a time. Asynchronous events are synonymous to multi-threads. The key
* point here is that the threads run in the background and the user is free to carry on with other processes. Once an
* event is complete, the appropriate listener/callback method will be called. The listener then proceeds to carry out
* further processing depending on the needs of the user.
*
* The {@link EventManager} manages the events/threads that the user creates. Currently, the supported event operations
* are: <code>start</code>, <code>stop</code>, <code>getStatus</code>. For Synchronous events, the user is unable to
* start another (Synchronous) event if one is already running at the time. The running event would have to either be
* stopped or completed before a new event can be started.
*
* The Event-based Asynchronous Pattern makes available the advantages of multithreaded applications while hiding many
* of the complex issues inherent in multithreaded design. Using a class that supports this pattern can allow you to:-
* (1) Perform time-consuming tasks, such as downloads and database operations, "in the background," without
* interrupting your application. (2) Execute multiple operations simultaneously, receiving notifications when each
* completes. (3) Wait for resources to become available without stopping ("hanging") your application. (4) Communicate
* with pending asynchronous operations using the familiar events-and-delegates model.
*
* @see EventManager
* @see Event
*
*/
public class App {
boolean interactiveMode = false;
public static void main(String[] args) {
App app = new App();
app.setUp();
app.run();
}
/**
* App can run in interactive mode or not. Interactive mode == Allow user interaction with command line.
* Non-interactive is a quick sequential run through the available {@link EventManager} operations.
*/
public void setUp() {
Properties prop = new Properties();
String propFileName = "config.properties";
InputStream inputStream = App.class.getClassLoader().getResourceAsStream(propFileName);
if (inputStream != null) {
try {
prop.load(inputStream);
} catch (IOException e) {
}
String property = prop.getProperty("INTERACTIVE_MODE");
if (property.equalsIgnoreCase("YES")) {
interactiveMode = true;
}
}
}
public void run() {
if (interactiveMode) {
runInteractiveMode();
} else {
quickRun();
}
}
public void quickRun() {
EventManager eventManager = new EventManager();
try {
// Create an Asynchronous event.
int aEventID = eventManager.createAsyncEvent(60);
System.out.println("Event [" + aEventID + "] has been created.");
eventManager.startEvent(aEventID);
System.out.println("Event [" + aEventID + "] has been started.");
// Create a Synchronous event.
int sEventID = eventManager.createSyncEvent(60);
System.out.println("Event [" + sEventID + "] has been created.");
eventManager.startEvent(sEventID);
System.out.println("Event [" + sEventID + "] has been started.");
eventManager.getStatus(aEventID);
eventManager.getStatus(sEventID);
eventManager.stopEvent(aEventID);
System.out.println("Event [" + aEventID + "] has been stopped.");
eventManager.stopEvent(sEventID);
System.out.println("Event [" + sEventID + "] has been stopped.");
} catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException
| InvalidOperationException e) {
System.out.println(e.getMessage());
}
}
public void runInteractiveMode() {
EventManager eventManager = new EventManager();
Scanner s = new Scanner(System.in);
int option = 0;
option = -1;
while (option != 5) {
System.out
.println("(1) START_EVENT \n(2) STOP_EVENT \n(3) STATUS_OF_EVENT \n(4) STATUS_OF_ALL_EVENTS \n(5) EXIT");
System.out.print("Choose [1,2,3,4,5]: ");
option = s.nextInt();
if (option == 1) {
s.nextLine();
System.out.print("(A)sync or (S)ync event?: ");
String eventType = s.nextLine();
System.out.print("How long should this event run for (in seconds)?: ");
int eventTime = s.nextInt();
if (eventType.equalsIgnoreCase("A")) {
try {
int eventID = eventManager.createAsyncEvent(eventTime);
System.out.println("Event [" + eventID + "] has been created.");
eventManager.startEvent(eventID);
System.out.println("Event [" + eventID + "] has been started.");
} catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) {
System.out.println(e.getMessage());
}
} else if (eventType.equalsIgnoreCase("S")) {
try {
int eventID = eventManager.createSyncEvent(eventTime);
System.out.println("Event [" + eventID + "] has been created.");
eventManager.startEvent(eventID);
System.out.println("Event [" + eventID + "] has been started.");
} catch (MaxNumOfEventsAllowedException | InvalidOperationException | LongRunningEventException
| EventDoesNotExistException e) {
System.out.println(e.getMessage());
}
} else {
System.out.println("Unknown event type.");
}
} else if (option == 2) {
System.out.print("Event ID: ");
int eventID = s.nextInt();
try {
eventManager.stopEvent(eventID);
System.out.println("Event [" + eventID + "] has been stopped.");
} catch (EventDoesNotExistException e) {
System.out.println(e.getMessage());
}
} else if (option == 3) {
System.out.print("Event ID: ");
int eventID = s.nextInt();
try {
eventManager.getStatus(eventID);
} catch (EventDoesNotExistException e) {
System.out.println(e.getMessage());
}
} else if (option == 4) {
eventManager.getStatusOfAllEvents();
}
}
s.close();
}
}

View File

@ -0,0 +1,88 @@
/**
* The MIT License Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.iluwatar.event.asynchronous;
/**
*
* Each Event runs as a separate/individual thread.
*
*/
public class Event implements IEvent, Runnable {
private int eventID;
private int eventTime;
private Thread thread;
private long counter = 0;
private boolean isComplete = false;
private ThreadCompleteListener eventListener;
public Event(int eventID, int eventTime) {
this.eventID = eventID;
this.eventTime = eventTime;
}
@Override
public void start() {
thread = new Thread(this);
thread.start();
}
@Override
public void stop() {
thread.interrupt();
}
@Override
public void status() {
if (!isComplete) {
System.out.println("[" + eventID + "] I am at not done. [" + counter + "%]");
} else {
System.out.println("[" + eventID + "] I am done.");
}
}
@Override
public void run() {
long currentTime = System.currentTimeMillis();
long endTime = currentTime + (eventTime * 1000);
while (System.currentTimeMillis() < endTime) {
try {
counter += 1;
Thread.sleep(5000); // Sleep for 5 seconds.
} catch (InterruptedException e) {
return;
}
}
isComplete = true;
notifyListener();
}
public final void addListener(final ThreadCompleteListener listener) {
this.eventListener = listener;
}
public final void removeListener(final ThreadCompleteListener listener) {
this.eventListener = null;
}
private final void notifyListener() {
if (eventListener != null) {
eventListener.notifyOfThreadComplete(eventID);
}
}
}

View File

@ -0,0 +1,26 @@
/**
* The MIT License Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.iluwatar.event.asynchronous;
public class EventDoesNotExistException extends Exception {
private static final long serialVersionUID = -3398463738273811509L;
public EventDoesNotExistException(String message) {
super(message);
}
}

View File

@ -0,0 +1,148 @@
/**
* The MIT License Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.iluwatar.event.asynchronous;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
/**
*
* EventManager handles and maintains a pool of event threads. {@link Event} threads are created upon user request. Thre
* are two types of events; Asynchronous and Synchronous. There can be multiple Asynchronous events running at once but
* only one Synchronous event running at a time. Currently supported event operations are: start, stop, and getStatus.
* Once an event is complete, it then notifies EventManager through a listener. The EventManager then takes the event
* out of the pool.
*
*/
public class EventManager implements ThreadCompleteListener {
private int minID = 1;
private int maxID = Integer.MAX_VALUE - 1; // Be cautious of overflows.
private int maxRunningEvents = 1000; // no particular reason. Just don't wanna have too many running events. :)
private int maxEventTime = 1800; // in seconds / 30 minutes.
private int currentlyRunningSyncEvent = -1;
private Random rand;
private Map<Integer, Event> eventPool;
public EventManager() {
rand = new Random(1);
eventPool = new ConcurrentHashMap<Integer, Event>(maxRunningEvents);
}
// Create a Synchronous event.
public int createSyncEvent(int eventTime)
throws MaxNumOfEventsAllowedException, InvalidOperationException, LongRunningEventException {
int eventID = createEvent(eventTime);
if (currentlyRunningSyncEvent != -1) {
throw new InvalidOperationException(
"Event [" + currentlyRunningSyncEvent + "] is still running. Please wait until it finishes and try again.");
}
currentlyRunningSyncEvent = eventID;
return eventID;
}
// Create an Asynchronous event.
public int createAsyncEvent(int eventTime) throws MaxNumOfEventsAllowedException, LongRunningEventException {
return createEvent(eventTime);
}
private int createEvent(int eventTime) throws MaxNumOfEventsAllowedException, LongRunningEventException {
if (eventPool.size() == maxRunningEvents) {
throw new MaxNumOfEventsAllowedException("Too many events are running at the moment. Please try again later.");
}
if (eventTime >= maxEventTime) {
throw new LongRunningEventException(
"Maximum event time allowed is " + maxEventTime + " seconds. Please try again.");
}
int newEventID = generateID();
Event newEvent = new Event(newEventID, eventTime);
newEvent.addListener(this);
eventPool.put(newEventID, newEvent);
return newEventID;
}
public void startEvent(int eventID) throws EventDoesNotExistException {
if (!eventPool.containsKey(eventID)) {
throw new EventDoesNotExistException(eventID + " does not exist.");
}
eventPool.get(eventID).start();
}
public void stopEvent(int eventID) throws EventDoesNotExistException {
if (!eventPool.containsKey(eventID)) {
throw new EventDoesNotExistException(eventID + " does not exist.");
}
if (eventID == currentlyRunningSyncEvent) {
currentlyRunningSyncEvent = -1;
}
eventPool.get(eventID).stop();
eventPool.remove(eventID);
}
public void getStatus(int eventID) throws EventDoesNotExistException {
if (!eventPool.containsKey(eventID)) {
throw new EventDoesNotExistException(eventID + " does not exist.");
}
eventPool.get(eventID).status();
}
@SuppressWarnings("rawtypes")
public void getStatusOfAllEvents() {
Iterator it = eventPool.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
((Event) pair.getValue()).status();
}
}
/**
* Returns a pseudo-random number between min and max, inclusive. The difference between min and max can be at most
* <code>Integer.MAX_VALUE - 1</code>.
*/
private int generateID() {
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((maxID - minID) + 1) + minID;
while (eventPool.containsKey(randomNum)) {
randomNum = rand.nextInt((maxID - minID) + 1) + minID;
}
return randomNum;
}
/**
* Callback from an {@link Event} (once it is complete). The Event is then removed from the pool.
*/
@Override
public void notifyOfThreadComplete(int eventID) {
eventPool.get(eventID).status();
eventPool.remove(eventID);
}
}

View File

@ -0,0 +1,27 @@
/**
* The MIT License Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.iluwatar.event.asynchronous;
public interface IEvent {
public void start();
public void stop();
public void status();
}

View File

@ -0,0 +1,27 @@
/**
* The MIT License Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.iluwatar.event.asynchronous;
public class InvalidOperationException extends Exception {
private static final long serialVersionUID = -6191545255213410803L;
public InvalidOperationException(String message) {
super(message);
}
}

View File

@ -0,0 +1,26 @@
/**
* The MIT License Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.iluwatar.event.asynchronous;
public class LongRunningEventException extends Exception {
private static final long serialVersionUID = -483423544320148809L;
public LongRunningEventException(String message) {
super(message);
}
}

View File

@ -0,0 +1,26 @@
/**
* The MIT License Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.iluwatar.event.asynchronous;
public class MaxNumOfEventsAllowedException extends Exception {
private static final long serialVersionUID = -8430876973516292695L;
public MaxNumOfEventsAllowedException(String message) {
super(message);
}
}

View File

@ -0,0 +1,21 @@
/**
* The MIT License Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.iluwatar.event.asynchronous;
public interface ThreadCompleteListener {
void notifyOfThreadComplete(final int eventID);
}

View File

@ -0,0 +1 @@
INTERACTIVE_MODE=NO

View File

@ -0,0 +1,32 @@
/**
* The MIT License Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.iluwatar.event.asynchronous;
import java.io.IOException;
import org.junit.Test;
/**
* Tests that EventAsynchronous example runs without errors.
*/
public class AppTest {
@Test
public void test() throws IOException {
String[] args = {};
App.main(args);
}
}

View File

@ -0,0 +1,73 @@
/**
* The MIT License Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.iluwatar.event.asynchronous;
import org.junit.Before;
import org.junit.Test;
/**
*
* Application test
*
*/
public class EventAsynchronousTest {
App app;
@Before
public void setUp() {
app = new App();
}
@Test
public void testAsynchronousEvent() {
EventManager eventManager = new EventManager();
try {
int aEventID = eventManager.createAsyncEvent(60);
eventManager.startEvent(aEventID);
eventManager.stopEvent(aEventID);
} catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) {
System.out.println(e.getMessage());
}
}
@Test
public void testSynchronousEvent() {
EventManager eventManager = new EventManager();
try {
int sEventID = eventManager.createSyncEvent(60);
eventManager.startEvent(sEventID);
eventManager.stopEvent(sEventID);
} catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException
| InvalidOperationException e) {
System.out.println(e.getMessage());
}
}
@Test
public void testUnsuccessfulSynchronousEvent() {
EventManager eventManager = new EventManager();
try {
int sEventID = eventManager.createSyncEvent(60);
eventManager.startEvent(sEventID);
sEventID = eventManager.createSyncEvent(60);
eventManager.startEvent(sEventID);
} catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException
| InvalidOperationException e) {
System.out.println(e.getMessage());
}
}
}