├── LICENSE ├── README.md └── api ├── pom.xml └── src ├── main └── java │ └── com │ └── asyncj │ └── core │ └── api │ ├── ActorManager.java │ ├── ActorManagerThread.java │ ├── ActorMessage.java │ ├── ActorThread.java │ └── article │ ├── eightstations │ ├── Railway.java │ ├── RailwayTest.java │ └── Train.java │ ├── lotoftrains │ ├── Railway.java │ ├── RailwayTest.java │ └── Train.java │ ├── mpsclatency │ ├── Railway.java │ ├── ThreeProducersOneConsumerRailwayTest.java │ └── Train.java │ ├── onetrain │ ├── RailWay.java │ ├── RailWayTest.java │ └── Train.java │ ├── singlethread │ └── SingleThread.java │ ├── twotrains │ ├── Railway.java │ ├── RailwayTest.java │ └── Train.java │ └── ultrahighthroughput │ ├── RailWay.java │ ├── Train.java │ └── UltraHighThroughputRawRailwayTest.java └── test └── java └── com └── asyncj └── core └── api └── examples ├── fork ├── Actor1Impl.java ├── Actor2Impl.java └── ForkExample.java ├── forkjoin ├── Actor1Impl.java ├── Actor2Impl.java └── ForkJoinExample.java ├── pingpong ├── Actor1Impl.java ├── Actor2Impl.java └── PingPongExample.java └── plainjava ├── Actor1Impl.java ├── Actor2Impl.java └── PlainJavaExample.java /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | core 2 | ==== 3 | -------------------------------------------------------------------------------- /api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.asyncj.core.api 8 | api 9 | 0.1-SNAPSHOT 10 | 11 | 12 | 13 | junit 14 | junit 15 | 4.11 16 | test 17 | 18 | 19 | 20 | commons-collections 21 | commons-collections 22 | 3.2.1 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/ActorManager.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api; 17 | 18 | import java.lang.reflect.InvocationHandler; 19 | import java.lang.reflect.Method; 20 | import java.lang.reflect.Proxy; 21 | import java.util.*; 22 | import java.util.concurrent.BlockingQueue; 23 | import java.util.concurrent.LinkedBlockingQueue; 24 | 25 | /** 26 | * User: APOPOV 27 | * Date: 05.10.13 28 | */ 29 | public class ActorManager { 30 | 31 | 32 | private BlockingQueue queue = new LinkedBlockingQueue(); 33 | 34 | private Map actorToProxy = (new LinkedHashMap()); 35 | 36 | public ActorManager() { 37 | 38 | int availableProcessors = Runtime.getRuntime().availableProcessors() * 20; 39 | 40 | ActorManagerThread actorManagerThread = new ActorManagerThread(queue); 41 | for (int i = 0; i < availableProcessors; i++) { 42 | actorManagerThread.addNewActorThread(); 43 | } 44 | 45 | actorManagerThread.start(); 46 | } 47 | 48 | 49 | @SuppressWarnings("unchecked") 50 | public synchronized T createActor(Object obj) { 51 | MethodHandler h = new MethodHandler(obj); 52 | T t = (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), h); 53 | actorToProxy.put(obj, (Proxy) t); 54 | return t; 55 | } 56 | 57 | public synchronized List createActors(Object obj, int count) { 58 | List ts = new ArrayList(); 59 | for (int i = 0; i < count; i++) { 60 | ts.add(this.createActor(obj)); 61 | } 62 | return ts; 63 | } 64 | 65 | @SuppressWarnings("unchecked") 66 | public T getReference(T actor1) { 67 | return (T) actorToProxy.get(actor1); 68 | } 69 | 70 | public void unblockResult(Object actor1) { 71 | Proxy proxy = (Proxy) getReference(actor1); 72 | ((MethodHandler) Proxy.getInvocationHandler(proxy)).unblockResult(); 73 | } 74 | 75 | class MethodHandler implements InvocationHandler { 76 | 77 | private Object obj; 78 | 79 | private final Object lock = new Object(); 80 | 81 | public MethodHandler(Object obj) { 82 | this.obj = obj; 83 | } 84 | 85 | @Override 86 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 87 | 88 | if ("hashCode".equals(method.getName()) ) { 89 | return obj.hashCode(); 90 | } 91 | 92 | if ("equals".equals(method.getName()) ) { 93 | return obj.equals(args); 94 | } 95 | 96 | if ("toString".equals(method.getName()) ) { 97 | return obj.toString(); 98 | } 99 | // a method invocation will send the message to a blocking queue 100 | int i=0; 101 | if (args != null) { 102 | for (Object arg : args) { 103 | Proxy proxy1 = actorToProxy.get(arg); 104 | if (proxy1 != null) { 105 | args[i] = proxy1; 106 | } 107 | i++; 108 | } 109 | } 110 | 111 | Class returnType = method.getReturnType(); 112 | if ("void".equals(returnType.getName())) { 113 | queue.put(new ActorMessage(ActorMessage.METHOD_CALL, obj, method, args)); 114 | return null; 115 | } 116 | else { 117 | 118 | //if the return class is an actor interface then return a new instance of the proxy 119 | //to the user and associate it with the current proxy/actor. 120 | //the proxy should send all messages inside with a type METHOD_RESULT 121 | // and when the actor thread will execute the 122 | // method which will return the result of the actual actor, then the actor thread will send 123 | // a message to the Actor Manager Thread. The AMT will start sending messages to the new actor... 124 | //when the actor will be instantiated later it should receive all messages 125 | //that has been sent to it before 126 | 127 | //block the current thread and wait for the value from a future object 128 | synchronized (lock) { 129 | lock.wait(); 130 | return method.invoke(obj, args); 131 | } 132 | } 133 | } 134 | 135 | public void unblockResult() { 136 | synchronized (lock) { 137 | lock.notify(); 138 | } 139 | } 140 | 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/ActorManagerThread.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api; 17 | 18 | import java.util.LinkedHashMap; 19 | import java.util.LinkedList; 20 | import java.util.Map; 21 | import java.util.Queue; 22 | import java.util.concurrent.BlockingQueue; 23 | import java.util.concurrent.LinkedBlockingQueue; 24 | 25 | /** 26 | * User: APOPOV 27 | * Date: 05.10.13 28 | */ 29 | public class ActorManagerThread extends Thread { 30 | 31 | private BlockingQueue queue; 32 | private Map> busyQueueMap = new LinkedHashMap>(); 33 | private Queue> queuePool = new LinkedList>(); 34 | 35 | private Queue msgCache = new LinkedList(); 36 | private boolean offered; 37 | private int prevSize = Integer.MAX_VALUE; 38 | 39 | public ActorManagerThread(BlockingQueue queue) { 40 | this.queue = queue; 41 | } 42 | 43 | @Override 44 | public void run() { 45 | boolean process = true; 46 | while (process) { 47 | try { 48 | ActorMessage message = queue.take(); 49 | 50 | if (ActorMessage.METHOD_CALL.equals(message.getType())) { 51 | //1. find a queue by the actor 52 | Object actor = message.getActor(); 53 | BlockingQueue actorQueue = busyQueueMap.get(actor); 54 | if (actorQueue == null) { 55 | actorQueue = queuePool.poll(); 56 | 57 | if (actorQueue == null) { 58 | // we do not need to block the thread but rather save the message in the local cache. 59 | msgCache.add(message); 60 | //System.out.println("Putting messages to a cache"); 61 | if (!offered) { 62 | // then the pool is empty. 63 | 64 | // then put a new com.asyncj.core.api.ActorMessage with type to process the msgCache 65 | offered = queue.offer(new ActorMessage(ActorMessage.PROCESS_DELAYED_MESSAGES, null, null, null)); 66 | if (!offered) { 67 | System.out.println("Can't offer to process delayed messages. The queue is full"); 68 | } 69 | } 70 | } 71 | else { 72 | busyQueueMap.put(actor, actorQueue); 73 | } 74 | } 75 | if (actorQueue != null) { 76 | actorQueue.put(message); 77 | } 78 | //2. and put the message into that queue 79 | } 80 | else 81 | if (ActorMessage.WORKER_IS_READY.equals(message.getType())) { 82 | Object actor = message.getActor(); 83 | //System.out.println("Worker is ready"); 84 | 85 | BlockingQueue actorMessages = busyQueueMap.get(actor); 86 | 87 | if (actorMessages != null && actorMessages.isEmpty()) { 88 | BlockingQueue removed = busyQueueMap.remove(actor); 89 | queuePool.add(removed); 90 | } 91 | 92 | //the last message is received for actor system. Let's shutdown it. 93 | /*if (busyQueueMap.isEmpty()) { 94 | ActorMessage poisonPill = new ActorMessage(ActorMessage.POISON_PILL, null, null, null); 95 | for (BlockingQueue blockingQueue : queuePool) { 96 | blockingQueue.add(poisonPill); 97 | } 98 | queue.offer(poisonPill); 99 | }*/ 100 | } 101 | else 102 | if (ActorMessage.PROCESS_DELAYED_MESSAGES.equals(message.getType())) { 103 | int currentSize = msgCache.size(); 104 | 105 | if (currentSize > 2 && currentSize > prevSize) { 106 | System.out.println("msgCache size: " + msgCache.size()); 107 | 108 | for (int i = 0; i < currentSize; i++) 109 | { 110 | addNewActorThread(); 111 | } 112 | } 113 | prevSize = currentSize; 114 | 115 | ActorMessage peek = msgCache.peek(); 116 | 117 | while (peek != null) { 118 | //try to offer to the main queue 119 | boolean offer = queue.offer(peek); 120 | if (!offer) { 121 | System.out.println("Can't offer to process delayed message. The queue is full"); 122 | // the problem should be escalated 123 | } 124 | else { 125 | msgCache.remove(); 126 | peek = msgCache.peek(); 127 | } 128 | } 129 | offered = false; 130 | } 131 | else 132 | if (ActorMessage.POISON_PILL.equals(message.getType())) { 133 | System.out.println("Poison pill received... Shutting down the actor manager's thread"); 134 | process = false; 135 | } 136 | 137 | } catch (InterruptedException e) { 138 | throw new RuntimeException(e); 139 | } 140 | } 141 | } 142 | 143 | 144 | public void addNewActorThread() { 145 | BlockingQueue blockingQueue = new LinkedBlockingQueue(); 146 | new ActorThread(blockingQueue, queue).start(); 147 | queuePool.add(blockingQueue); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/ActorMessage.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api; 17 | 18 | import java.lang.reflect.Method; 19 | 20 | /** 21 | * User: APOPOV 22 | * Date: 05.10.13 23 | */ 24 | public class ActorMessage { 25 | public static final String METHOD_CALL = "methodCall"; 26 | public static final String WORKER_IS_READY = "workerIsReady"; 27 | public static final String PROCESS_DELAYED_MESSAGES = "processDelayedMessages"; 28 | public static final String POISON_PILL = "poisonPill"; 29 | private final String type; 30 | private final Object actor; 31 | private final Method method; 32 | private final Object[] args; 33 | 34 | public ActorMessage(String type, Object actor, Method method, Object[] args) { 35 | this.type = type; 36 | this.actor = actor; 37 | this.method = method; 38 | this.args = args; 39 | } 40 | 41 | public String getType() { 42 | return type; 43 | } 44 | 45 | public Object getActor() { 46 | return actor; 47 | } 48 | 49 | public Method getMethod() { 50 | return method; 51 | } 52 | 53 | public Object[] getArgs() { 54 | return args; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/ActorThread.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api; 17 | 18 | import java.lang.reflect.InvocationTargetException; 19 | import java.lang.reflect.Method; 20 | import java.util.concurrent.BlockingQueue; 21 | import java.util.concurrent.TimeUnit; 22 | 23 | /** 24 | * User: APOPOV 25 | * Date: 05.10.13 26 | */ 27 | public class ActorThread extends Thread { 28 | private BlockingQueue actorMessages; 29 | private BlockingQueue parentQueue; 30 | private Object actor; 31 | 32 | public ActorThread(BlockingQueue actorMessages, BlockingQueue parentQueue) { 33 | this.actorMessages = actorMessages; 34 | this.parentQueue = parentQueue; 35 | } 36 | 37 | @Override 38 | public void run() { 39 | boolean process = true; 40 | while (process) { 41 | try { 42 | ActorMessage msg = actorMessages.poll(5, TimeUnit.MILLISECONDS); 43 | if (msg == null) { 44 | if (actor != null) { 45 | //System.out.println("Ready..."); 46 | parentQueue.put(new ActorMessage(ActorMessage.WORKER_IS_READY, actor, null, null)); 47 | actor = null; 48 | } 49 | msg = actorMessages.take(); 50 | } 51 | 52 | if (ActorMessage.METHOD_CALL.equals(msg.getType())) { 53 | Method m = msg.getMethod(); 54 | actor = msg.getActor(); 55 | Object invoke = m.invoke(actor, msg.getArgs()); 56 | } 57 | else 58 | if (ActorMessage.POISON_PILL.equals(msg.getType())) { 59 | System.out.println("Poison pill received... Shutting down the actor's thread"); 60 | process = false; 61 | } 62 | 63 | } catch (InterruptedException e) { 64 | throw new RuntimeException(e); 65 | } catch (IllegalAccessException e) { 66 | throw new RuntimeException(e); 67 | } catch (InvocationTargetException e) { 68 | throw new RuntimeException(e); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/eightstations/Railway.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.eightstations; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | /** 6 | * @author Aliaksei Papou 7 | * @since 23.11.13 8 | */ 9 | public class Railway { 10 | 11 | private final int stationCount; 12 | private final Train[] train; 13 | private final AtomicInteger[] stationIndex; 14 | 15 | public Railway(int trainCount, int trainCapacity, int stationCount) { 16 | this.stationCount = stationCount; 17 | stationIndex = new AtomicInteger[trainCount]; 18 | train = new Train[trainCount]; 19 | for (int i = 0; i < trainCount; i++) { 20 | stationIndex[i] = new AtomicInteger(); 21 | train[i] = new Train(trainCapacity); 22 | } 23 | } 24 | 25 | public Train waitTrainOnStation(final int trainNo, final int stationNo) { 26 | while (stationIndex[trainNo].get() % stationCount != stationNo) { 27 | Thread.yield(); 28 | } 29 | return train[trainNo]; 30 | } 31 | 32 | public void sendTrain(final int trainNo) { 33 | stationIndex[trainNo].getAndIncrement(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/eightstations/RailwayTest.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.eightstations; 2 | 3 | /** 4 | * 5 | * @author Aliaksei Papou 6 | * @since 23.11.13 7 | */ 8 | public class RailwayTest { 9 | 10 | public static void main(String[] args) { 11 | new RailwayTest().testRailWay(); 12 | } 13 | 14 | public void testRailWay() { 15 | final int stationCount = 8; 16 | final int trainCount = 32; 17 | final int trainCapacity = 256; 18 | 19 | final Railway railway = new Railway(trainCount, trainCapacity, stationCount); 20 | 21 | final long n = 20000000000l; 22 | 23 | for (int i = 1; i < stationCount; i++) { 24 | 25 | final int stationNo = i; 26 | new Thread() { 27 | long lastValue = 0; 28 | 29 | @Override 30 | public void run() { 31 | int trainIndex = 0; 32 | while (lastValue < n) { 33 | final int trainNo = trainIndex % trainCount; 34 | 35 | Train train = railway.waitTrainOnStation(trainNo, stationNo); 36 | int count = train.getCapacity() / (stationCount - 1); 37 | for (int i = 0; i < count; i++) { 38 | lastValue = train.getGoods(i); 39 | } 40 | railway.sendTrain(trainNo); 41 | 42 | trainIndex++; 43 | } 44 | } 45 | }.start(); 46 | 47 | } 48 | final long start = System.nanoTime(); 49 | 50 | long i = 0; 51 | int trainIndex = 0; 52 | while (i < n) { 53 | final int trainNo = trainIndex % trainCount; 54 | 55 | Train train = railway.waitTrainOnStation(trainNo, 0); 56 | int capacity = train.getCapacity() - train.goodsCount(); 57 | 58 | for (int j = 0; j < capacity; j++) { 59 | train.addGoods((int)i++); 60 | } 61 | railway.sendTrain(trainNo); 62 | 63 | trainIndex++; 64 | 65 | if (i % 10000000 == 0) { 66 | final long duration = System.nanoTime() - start; 67 | 68 | final long ops = (i * 1000L * 1000L * 1000L) / duration; 69 | System.out.format("ops/sec = %,d\n", ops); 70 | System.out.format("trains/sec = %,d\n", ops / trainCapacity); 71 | System.out.format("latency nanos = %.1f%n\n", duration / (float)(i) * (float) trainCapacity); 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/eightstations/Train.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.eightstations; 2 | 3 | /** 4 | * @author Aliaksei Papou 5 | * @since 23.11.13 6 | */ 7 | public class Train { 8 | 9 | private final long[] goodsArray; 10 | private int index; 11 | private int trainCapacity; 12 | 13 | public Train(int trainCapacity) { 14 | this.trainCapacity = trainCapacity; 15 | goodsArray = new long[trainCapacity]; 16 | } 17 | 18 | public int goodsCount() { 19 | return index; 20 | } 21 | 22 | public void addGoods(long i) { 23 | goodsArray[index++] = i; 24 | } 25 | 26 | public long getGoods(int i) { 27 | index--; 28 | return goodsArray[i]; 29 | } 30 | 31 | public int getCapacity() { 32 | return trainCapacity; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/lotoftrains/Railway.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.lotoftrains; 2 | 3 | 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | 6 | /** 7 | * @author Aliaksei Papou 8 | * @since 23.11.13 9 | */ 10 | public class Railway { 11 | 12 | private final int stationCount = 2; 13 | private final Train[] train; 14 | private final AtomicInteger[] stationIndex; 15 | 16 | public Railway(int trainCount, int trainCapacity) { 17 | stationIndex = new AtomicInteger[trainCount]; 18 | train = new Train[trainCount]; 19 | for (int i = 0; i < trainCount; i++) { 20 | stationIndex[i] = new AtomicInteger(); 21 | train[i] = new Train(trainCapacity); 22 | } 23 | } 24 | 25 | public Train waitTrainOnStation(final int trainNo, final int stationNo) { 26 | while (stationIndex[trainNo].get() % stationCount != stationNo) { 27 | Thread.yield(); 28 | } 29 | return train[trainNo]; 30 | } 31 | 32 | public void sendTrain(final int trainNo) { 33 | stationIndex[trainNo].getAndIncrement(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/lotoftrains/RailwayTest.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.lotoftrains; 2 | 3 | 4 | /** 5 | * 6 | * @author Aliaksei Papou 7 | * @since 23.11.13 8 | */ 9 | public class RailwayTest { 10 | 11 | public static void main(String[] args) { 12 | new RailwayTest().testRailWay(); 13 | } 14 | 15 | public void testRailWay() { 16 | final int trainCount = 256; 17 | final int trainCapacity = 128; 18 | 19 | final Railway railway = new Railway(trainCount, trainCapacity); 20 | 21 | final long n = 20000000000l; 22 | 23 | new Thread() { 24 | long lastValue = 0; 25 | 26 | @Override 27 | public void run() { 28 | int trainIndex = 0; 29 | while (lastValue < n) { 30 | final int trainNo = trainIndex % trainCount; 31 | 32 | Train train = railway.waitTrainOnStation(trainNo, 1); 33 | int count = train.goodsCount(); 34 | for (int i = 0; i < count; i++) { 35 | lastValue = train.getGoods(i); 36 | } 37 | railway.sendTrain(trainNo); 38 | 39 | trainIndex++; 40 | } 41 | } 42 | }.start(); 43 | 44 | final long start = System.nanoTime(); 45 | 46 | long i = 0; 47 | int trainIndex = 0; 48 | while (i < n) { 49 | final int trainNo = trainIndex % trainCount; 50 | 51 | Train train = railway.waitTrainOnStation(trainNo, 0); 52 | int capacity = train.getCapacity(); 53 | for (int j = 0; j < capacity; j++) { 54 | train.addGoods((int)i++); 55 | } 56 | railway.sendTrain(trainNo); 57 | 58 | trainIndex++; 59 | 60 | if (i % 1000000000 == 0) { 61 | final long duration = System.nanoTime() - start; 62 | 63 | final long ops = (i * 1000L * 1000L * 1000L) / duration; 64 | System.out.format("ops/sec = %,d\n", ops); 65 | System.out.format("trains/sec = %,d\n", ops / trainCapacity); 66 | System.out.format("latency nanos = %.1f%n\n", duration / (float)(i) * (float) trainCapacity); 67 | 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/lotoftrains/Train.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.lotoftrains; 2 | 3 | /** 4 | * @author Aliaksei Papou 5 | * @since 23.11.13 6 | */ 7 | public class Train { 8 | 9 | private final long[] goodsArray; 10 | private int index; 11 | private int trainCapacity; 12 | 13 | public Train(int trainCapacity) { 14 | this.trainCapacity = trainCapacity; 15 | goodsArray = new long[trainCapacity]; 16 | } 17 | 18 | 19 | public int goodsCount() { 20 | return index; 21 | } 22 | 23 | public void addGoods(long i) { 24 | goodsArray[index++] = i; 25 | } 26 | 27 | public long getGoods(int i) { 28 | index--; 29 | return goodsArray[i]; 30 | } 31 | 32 | public int getCapacity() { 33 | return trainCapacity; 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/mpsclatency/Railway.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.mpsclatency; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | /** 6 | * @author Aliaksei Papou 7 | * @since 23.11.13 8 | */ 9 | @SuppressWarnings("unused") 10 | public class Railway { 11 | 12 | private final int mask; 13 | private final Train[] train; 14 | 15 | public Railway(int trainCount, int trainCapacity, int stationCount) { 16 | mask = stationCount - 1; 17 | train = new Train[trainCount]; 18 | for (int i = 0; i < trainCount; i++) { 19 | train[i] = new Train(trainCapacity); 20 | } 21 | } 22 | 23 | public Train waitTrainOnStation(final int trainNo, final int stationNo) { 24 | while ((train[trainNo].stationIndex.get() & mask) != stationNo) { 25 | Thread.yield(); 26 | } 27 | return train[trainNo]; 28 | } 29 | 30 | public void sendTrain(final int trainNo) { 31 | final AtomicInteger stationIndex = train[trainNo].stationIndex; 32 | stationIndex.lazySet(stationIndex.get() + 1); 33 | } 34 | 35 | public void sendTrainToStation(int trainNo, int stationNo) { 36 | train[trainNo].stationIndex.set(stationNo); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/mpsclatency/ThreeProducersOneConsumerRailwayTest.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.mpsclatency; 2 | 3 | import java.util.Locale; 4 | 5 | /** 6 | *
  7 |  * This test shows a case with 3 producers and 1 consumer (3P:1C).
  8 |  *
  9 |  * The railway uses 65536 trains with capacity 3.
 10 |  * Trains go sequentially from one station (thread) to another.
 11 |  *
 12 |  * +----+
 13 |  * | P1 |------+
 14 |  * +----+      |
 15 |  *             v
 16 |  * +----+    +----+
 17 |  * | P2 |--->| C1 |
 18 |  * +----+    +----+
 19 |  *             ^
 20 |  * +----+      |
 21 |  * | P3 |------+
 22 |  * +----+
 23 |  *
 24 |  * For tests the following processor has been used:
 25 |  * Intel® Core™ i7-3632QM Processor (6M Cache, up to 3.20 GHz) BGA with 4 Cores
 26 |  * http://ark.intel.com/products/71670/Intel-Core-i7-3632QM-Processor-6M-Cache-up-to-3_20-GHz-BGA
 27 |  *
 28 |  * After some warming up of the CPU up to 3.20 GHz the following results achieved:
 29 |  *
 30 |  * Railway average test results
 31 |  * ops/sec       = 206,937,353
 32 |  * trains/sec    = 68,979,117
 33 |  * latency ns = 14.5
 34 |  *
 35 |  * The best result achieved:
 36 |  * ops/sec       = 296,305,364
 37 |  * trains/sec    = 98,768,454
 38 |  * latency ns = 10.1
 39 |  *
 40 |  *
 41 |  * To fill the difference the following results on the same hardware show Disruptor test for the same 3P:1C
 42 |  * https://github.com/LMAX-Exchange/disruptor/blob/master/src/perftest/java/com/lmax/disruptor/ThreePublisherToOneProcessorSequencedThroughputTest.java
 43 |  *
 44 |  * Starting Queue tests
 45 |  * Run 0, BlockingQueue=4,353,504 ops/sec
 46 |  * Run 1, BlockingQueue=4,353,504 ops/sec
 47 |  * Run 2, BlockingQueue=4,328,067 ops/sec
 48 |  * Run 3, BlockingQueue=4,316,857 ops/sec
 49 |  * Starting Disruptor tests
 50 |  * Run 0, Disruptor=11,467,889 ops/sec
 51 |  * Run 1, Disruptor=11,280,315 ops/sec
 52 |  * Run 2, Disruptor=11,286,681 ops/sec
 53 |  * Run 3, Disruptor=11,254,924 ops/sec
 54 |  *
 55 |  * Below the results of running 3P:1C test with batching (10 items per a batch):
 56 |  * https://github.com/LMAX-Exchange/disruptor/blob/master/src/perftest/java/com/lmax/disruptor/ThreePublisherToOneProcessorBatchThroughputTest.java
 57 |  *
 58 |  * Starting Queue tests
 59 |  * Run 0, BlockingQueue=4,546,281 ops/sec
 60 |  * Run 1, BlockingQueue=4,508,769 ops/sec
 61 |  * Run 2, BlockingQueue=4,101,386 ops/sec
 62 |  * Run 3, BlockingQueue=4,124,561 ops/sec
 63 |  * Starting Disruptor tests
 64 |  * Run 0, Disruptor=116,009,280 ops/sec
 65 |  * Run 1, Disruptor=128,205,128 ops/sec
 66 |  * Run 2, Disruptor=101,317,122 ops/sec
 67 |  * Run 3, Disruptor=98,716,683 ops/sec
 68 |  *
 69 |  * Summary
 70 |  *
 71 |  * The Best Results:
 72 |  * Railway        = 296,305,364 ops/sec
 73 |  * Disruptor      = 128,205,128 ops/sec
 74 |  * BlockingQueue  =   4,546,281 ops/sec
 75 |  * 
76 | * 77 | * @author Aliaksei Papou 78 | * @since 23.11.13 79 | */ 80 | public class ThreeProducersOneConsumerRailwayTest { 81 | 82 | public static void main(String[] args) { 83 | new ThreeProducersOneConsumerRailwayTest().testRailWay(); 84 | } 85 | 86 | public void testRailWay() { 87 | Locale.setDefault(Locale.US); 88 | final int stationCount = 4; 89 | final int trainCount = 64 * 1024; 90 | final int mask = trainCount - 1; 91 | final int lastStationNo = stationCount - 1; 92 | final short trainCapacity = (stationCount - 1) ; 93 | 94 | final Railway railway = new Railway(trainCount, trainCapacity, stationCount); 95 | 96 | final long n = 20l * 1000 * 1000 * 1000; 97 | 98 | // starting producers 99 | for (int i = 0; i < lastStationNo; i++) { 100 | 101 | final int stationNo = i; 102 | new Thread() { 103 | long lastValue = 0; 104 | 105 | @Override 106 | public void run() { 107 | long trainIndex = 0; 108 | while (lastValue < n) { 109 | final int trainNo = (int) (trainIndex & mask); 110 | 111 | Train train = railway.waitTrainOnStation(trainNo, stationNo); 112 | int count = train.getCapacity() / trainCapacity; 113 | for (int i = 0; i < count; i++) { 114 | train.addGoods(trainIndex); 115 | } 116 | 117 | railway.sendTrain(trainNo); 118 | 119 | trainIndex++; 120 | } 121 | } 122 | }.start(); 123 | 124 | } 125 | final long start = System.nanoTime(); 126 | 127 | long i = 0; 128 | long trainIndex = 0; 129 | 130 | while (i < n) { 131 | final int trainNo = (int) (trainIndex & mask); 132 | 133 | Train train = railway.waitTrainOnStation(trainNo, lastStationNo); 134 | int goodsCount = train.goodsCount(); 135 | 136 | long goods; 137 | 138 | for (int j = 0; j < goodsCount; j++) { 139 | goods = train.getGoods(j); 140 | i++; 141 | } 142 | railway.sendTrain(trainNo); 143 | 144 | trainIndex++; 145 | 146 | if ((trainIndex % 100000000) == 0) { 147 | final long duration = System.nanoTime() - start; 148 | 149 | final long ops = (i * 1000L * 1000L * 1000L) / duration; 150 | System.out.format("ops/sec = %,d\n", ops); 151 | System.out.format("trains/sec = %,d\n", ops / trainCapacity); 152 | System.out.format("latency ns = %.1f%n\n", duration / (float) (i) * (float) trainCapacity); 153 | } 154 | } 155 | 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/mpsclatency/Train.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.mpsclatency; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | /** 6 | * @author Aliaksei Papou 7 | * @since 23.11.13 8 | */ 9 | public class Train { 10 | 11 | private static int trainCapacity; 12 | private final long[] goodsArray; 13 | public AtomicInteger stationIndex = new AtomicInteger(); 14 | private int index; 15 | 16 | public Train(int trainCapacity) { 17 | this.trainCapacity = trainCapacity; 18 | goodsArray = new long[trainCapacity]; 19 | } 20 | 21 | public int goodsCount() { 22 | return index; 23 | } 24 | 25 | public void addGoods(long i) { 26 | goodsArray[index++] = i; 27 | } 28 | 29 | public long getGoods(int i) { 30 | index--; 31 | return goodsArray[i]; 32 | } 33 | 34 | public int getCapacity() { 35 | return trainCapacity; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/onetrain/RailWay.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.onetrain; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | /** 6 | * @author Aliaksei Papou 7 | * @since 23.11.13 8 | */ 9 | public class Railway { 10 | 11 | private final int stationCount = 2; 12 | private final Train train = new Train(); 13 | private final AtomicInteger stationIndex = new AtomicInteger(); 14 | 15 | public Train waitTrainOnStation(final int stationNo) { 16 | while (stationIndex.get() % stationCount != stationNo) { 17 | Thread.yield(); 18 | } 19 | return train; 20 | } 21 | public void sendTrain() { 22 | stationIndex.getAndIncrement(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/onetrain/RailWayTest.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.onetrain; 2 | 3 | /** 4 | * 5 | * @author Aliaksei Papou 6 | * @since 23.11.13 7 | */ 8 | public class RailwayTest { 9 | public static void main(String[] args) { 10 | new RailwayTest().testRailWay(); 11 | } 12 | 13 | public void testRailWay() { 14 | final Railway railway = new Railway(); 15 | 16 | final long n = 20000000000l; 17 | 18 | new Thread() { 19 | long lastValue = 0; 20 | 21 | @Override 22 | public void run() { 23 | 24 | while (lastValue < n) { 25 | Train train = railway.waitTrainOnStation(1); 26 | int count = train.goodsCount(); 27 | for (int i = 0; i < count; i++) { 28 | lastValue = train.getGoods(i); 29 | } 30 | railway.sendTrain(); 31 | } 32 | } 33 | }.start(); 34 | 35 | final long start = System.nanoTime(); 36 | 37 | long i = 0; 38 | while (i < n) { 39 | Train train = railway.waitTrainOnStation(0); 40 | int capacity = train.getCapacity(); 41 | for (int j = 0; j < capacity; j++) { 42 | train.addGoods((int)i++); 43 | } 44 | railway.sendTrain(); 45 | 46 | if (i % 1000000 == 0) { 47 | final long duration = System.nanoTime() - start; 48 | 49 | final long ops = (i * 1000L * 1000L * 1000L) / duration; 50 | System.out.format("ops/sec = %,d\n", ops); 51 | System.out.format("trains/sec = %,d\n", ops / Train.CAPACITY); 52 | System.out.format("latency nanos = %.3f%n\n", duration / (float)(i) * (float) Train.CAPACITY); 53 | 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/onetrain/Train.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.onetrain; 2 | 3 | /** 4 | * @author Aliaksei Papou 5 | * @since 23.11.13 6 | */ 7 | public class Train { 8 | 9 | public static int CAPACITY = 2*1024; 10 | 11 | private final long[] goodsArray = new long[CAPACITY]; 12 | 13 | private int index; 14 | 15 | public int goodsCount() { 16 | return index; 17 | } 18 | 19 | public void addGoods(long i) { 20 | goodsArray[index++] = i; 21 | } 22 | 23 | public long getGoods(int i) { 24 | index--; 25 | return goodsArray[i]; 26 | } 27 | 28 | public int getCapacity() { 29 | return CAPACITY; 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/singlethread/SingleThread.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.singlethread; 2 | 3 | import java.util.Locale; 4 | 5 | /** 6 | * @author Aliaksei Papou 7 | * @since 18.11.13 8 | */ 9 | public class SingleThread { 10 | 11 | private static final long ITERATIONS = 1000L * 1000L * 50L; 12 | 13 | public static void main(String[] args) { 14 | Locale.setDefault(Locale.US); 15 | new SingleThread(); 16 | } 17 | 18 | public SingleThread() { 19 | final long start = System.nanoTime(); 20 | 21 | long i = 0; 22 | while (i < ITERATIONS) { 23 | i++; 24 | } 25 | 26 | final long duration = System.nanoTime() - start; 27 | 28 | final long ops = (ITERATIONS * 1000L * 1000L * 1000L) / duration; 29 | System.out.format("ops/sec = %,d\n", ops); 30 | System.out.format("latency ns = %.3f%n", duration / (float)(ITERATIONS) ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/twotrains/Railway.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.twotrains; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | /** 6 | * @author Aliaksei Papou 7 | * @since 23.11.13 8 | */ 9 | public class Railway { 10 | 11 | private final int stationCount = 2; 12 | private final Train[] train = new Train[]{ 13 | new Train(), 14 | new Train(), 15 | }; 16 | 17 | private final AtomicInteger[] stationIndex = new AtomicInteger[]{ 18 | new AtomicInteger(0), 19 | new AtomicInteger(0), 20 | }; 21 | 22 | public Train waitTrainOnStation(final int trainNo, final int stationNo) { 23 | while (stationIndex[trainNo].get() % stationCount != stationNo) { 24 | Thread.yield(); 25 | } 26 | return train[trainNo]; 27 | } 28 | 29 | public void sendTrain(final int trainNo) { 30 | stationIndex[trainNo].getAndIncrement(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/twotrains/RailwayTest.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.twotrains; 2 | 3 | /** 4 | * 5 | * @author Aliaksei Papou 6 | * @since 23.11.13 7 | */ 8 | public class RailwayTest { 9 | 10 | public static void main(String[] args) { 11 | new RailwayTest().testRailWay(); 12 | } 13 | 14 | public void testRailWay() { 15 | final Railway railway = new Railway(); 16 | 17 | final long n = 20000000000l; 18 | 19 | new Thread() { 20 | long lastValue = 0; 21 | 22 | @Override 23 | public void run() { 24 | int trainIndex = 0; 25 | while (lastValue < n) { 26 | final int trainNo = trainIndex % 2; 27 | 28 | Train train = railway.waitTrainOnStation(trainNo, 1); 29 | int count = train.goodsCount(); 30 | for (int i = 0; i < count; i++) { 31 | lastValue = train.getGoods(i); 32 | } 33 | railway.sendTrain(trainNo); 34 | 35 | trainIndex++; 36 | } 37 | } 38 | }.start(); 39 | 40 | final long start = System.nanoTime(); 41 | 42 | long i = 0; 43 | int trainIndex = 0; 44 | while (i < n) { 45 | final int trainNo = trainIndex % 2; 46 | 47 | Train train = railway.waitTrainOnStation(trainNo, 0); 48 | int capacity = train.getCapacity(); 49 | for (int j = 0; j < capacity; j++) { 50 | train.addGoods((int)i++); 51 | } 52 | railway.sendTrain(trainNo); 53 | 54 | trainIndex++; 55 | 56 | if (i % 10000000 == 0) { 57 | final long duration = System.nanoTime() - start; 58 | 59 | final long ops = (i * 1000L * 1000L * 1000L) / duration; 60 | System.out.format("ops/sec = %,d\n", ops); 61 | System.out.format("trains/sec = %,d\n", ops / Train.CAPACITY); 62 | System.out.format("latency nanos = %.1f%n\n", duration / (float)(i) * (float) Train.CAPACITY); 63 | 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/twotrains/Train.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.twotrains; 2 | 3 | /** 4 | * @author Aliaksei Papou 5 | * @since 23.11.13 6 | */ 7 | public class Train { 8 | 9 | public static int CAPACITY = 32768; 10 | 11 | private final long[] goodsArray = new long[CAPACITY]; 12 | 13 | private int index; 14 | 15 | public int goodsCount() { 16 | return index; 17 | } 18 | 19 | public void addGoods(long i) { 20 | goodsArray[index++] = i; 21 | } 22 | 23 | public long getGoods(int i) { 24 | index--; 25 | return goodsArray[i]; 26 | } 27 | 28 | public int getCapacity() { 29 | return CAPACITY; 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/ultrahighthroughput/RailWay.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.ultrahighthroughput; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | /** 6 | * User: APOPOV 7 | * Date: 05.12.13 8 | */ 9 | public class RailWay { 10 | 11 | public static int TRAIN_COUNT = 8; 12 | private AtomicLong[] trainNoLong; 13 | 14 | private final Train[] train; 15 | 16 | private final int capacity; 17 | private final int mask; 18 | 19 | public RailWay(final int stationCount, int trainCapacity, int trainCount) { 20 | TRAIN_COUNT = trainCount; 21 | trainNoLong = new AtomicLong[trainCount]; 22 | train = new Train[trainCount]; 23 | for (int i = 0; i < trainCount; i++) { 24 | train[i] = new Train(trainCapacity); 25 | trainNoLong[i] = new AtomicLong(); 26 | } 27 | 28 | capacity = findNextPositivePowerOfTwo(stationCount); 29 | mask = capacity - 1; 30 | } 31 | 32 | public static int findNextPositivePowerOfTwo(final int value) { 33 | return 1 << (32 - Integer.numberOfLeadingZeros(value - 1)); 34 | } 35 | 36 | public Train waitTrainOnStation(final int trainIndex, final int stationNo) { 37 | while ((trainNoLong[trainIndex].get() & mask) != stationNo) { 38 | Thread.yield(); 39 | } 40 | return train[trainIndex]; 41 | } 42 | 43 | public void sendTrain(final int index) { 44 | final AtomicLong atomicLong = trainNoLong[index]; 45 | atomicLong.lazySet(atomicLong.get() + 1); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/ultrahighthroughput/Train.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.ultrahighthroughput; 2 | 3 | /** 4 | * User: APOPOV 5 | * Date: 15.10.13 6 | */ 7 | public class Train { 8 | 9 | public static int CAPACITY = 2*1024; 10 | 11 | private final long[] goodsArray; 12 | 13 | private int index; 14 | 15 | public Train(int capacity) { 16 | CAPACITY = capacity; 17 | goodsArray = new long[capacity]; 18 | } 19 | 20 | public int getCapacity() { 21 | return CAPACITY; 22 | } 23 | 24 | public void addGoods(long i) { 25 | goodsArray[index++] = i; 26 | } 27 | 28 | public int goodsCount() { 29 | return index; 30 | } 31 | 32 | public long getGoods(int i) { 33 | index--; 34 | return goodsArray[i]; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /api/src/main/java/com/asyncj/core/api/article/ultrahighthroughput/UltraHighThroughputRawRailwayTest.java: -------------------------------------------------------------------------------- 1 | package com.asyncj.core.api.article.ultrahighthroughput; 2 | 3 | import java.util.Locale; 4 | 5 | /** 6 | * User: APOPOV 7 | * Date: 15.10.13 8 | */ 9 | public class UltraHighThroughputRawRailwayTest { 10 | 11 | long k = 0; 12 | 13 | public static void main(String[] args) { 14 | new UltraHighThroughputRawRailwayTest(); 15 | } 16 | 17 | public UltraHighThroughputRawRailwayTest() { 18 | Locale.setDefault(Locale.US); 19 | final int trainCapacity = 2 * 1024; 20 | final int trainCount = findNextPositivePowerOfTwo(2); 21 | final int stationCount = 2; 22 | final RailWay railWay = new RailWay(stationCount, trainCapacity, trainCount); 23 | 24 | final long n = 20L * 1000 * 1000 * 1000; 25 | 26 | new Thread() { 27 | @Override 28 | public void run() { 29 | 30 | long trainIndex = 0; 31 | final int mask = trainCount - 1; 32 | while (true) { 33 | final int trainNo = (int) (trainIndex & mask); 34 | final Train train = railWay.waitTrainOnStation(trainNo, 1); 35 | 36 | int i = 0; 37 | final int count = train.getCapacity(); 38 | while (i < count) { 39 | long j = train.getGoods(i); 40 | i++; 41 | } 42 | railWay.sendTrain(trainNo); 43 | 44 | trainIndex++; 45 | } 46 | } 47 | }.start(); 48 | 49 | 50 | int trainIndex = 0; 51 | long i = 0; 52 | final int mask = trainCount - 1; 53 | final long start = System.nanoTime(); 54 | 55 | while (i < n) { 56 | final int trainNo = (trainIndex) & mask; 57 | final Train train = railWay.waitTrainOnStation(trainNo, 0); 58 | final int capacity = train.getCapacity(); 59 | int j = 0; 60 | while (j < capacity) { 61 | train.addGoods(i++); 62 | j++; 63 | } 64 | 65 | railWay.sendTrain(trainNo); 66 | 67 | trainIndex++; 68 | 69 | if (trainIndex % 1000000 == 0) { 70 | final long duration = System.nanoTime() - start; 71 | final long ops = (i * 1000L * 1000L * 1000L) / duration; 72 | System.out.format("ops/sec = %,d\n", ops); 73 | System.out.format("latency ns = %.3f%n", duration / (float) (i) * (float) trainCapacity); 74 | } 75 | } 76 | } 77 | 78 | 79 | public static int findNextPositivePowerOfTwo(final int value) { 80 | return 1 << (32 - Integer.numberOfLeadingZeros(value - 1)); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /api/src/test/java/com/asyncj/core/api/examples/fork/Actor1Impl.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api.examples.fork; 17 | 18 | import com.asyncj.core.api.ActorManager; 19 | 20 | class Actor1Impl implements ForkExample.Actor1 { 21 | 22 | private final int workLoad; 23 | int n; 24 | int count = 0; 25 | final long startTime; 26 | 27 | public Actor1Impl(int n) { 28 | this.n = n; 29 | workLoad = this.n / Runtime.getRuntime().availableProcessors(); 30 | 31 | startTime = System.currentTimeMillis(); 32 | } 33 | 34 | public void pong(ForkExample.Actor2 actor2, String s) { 35 | count++; 36 | 37 | if (count < n - Runtime.getRuntime().availableProcessors()) { 38 | if (count % 100000 == 0) 39 | System.out.println(count + " pings from - " + s); 40 | actor2.ping(this, count); 41 | } 42 | else { 43 | long endTime = System.currentTimeMillis(); 44 | System.out.println("super mega total count = " + count + ". In " + (endTime - startTime)/1000 + " seconds"); 45 | } 46 | } 47 | 48 | @Override 49 | public void startPings(ActorManager actorManager, int m) { 50 | if (m < workLoad) { 51 | ForkExample.Actor2 actor2 = actorManager.createActor(new Actor2Impl()); 52 | actor2.ping(this, m); 53 | } 54 | else { 55 | int m1 = m / 2; 56 | startPings(actorManager, m1); 57 | startPings(actorManager, m - m1); 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /api/src/test/java/com/asyncj/core/api/examples/fork/Actor2Impl.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api.examples.fork; 17 | 18 | class Actor2Impl implements ForkExample.Actor2 { 19 | 20 | public void ping(ForkExample.Actor1 actor1, int count) { 21 | if (count % 100000 == 0) 22 | System.out.println(count + " pongs"); 23 | actor1.pong(this, this.toString()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /api/src/test/java/com/asyncj/core/api/examples/fork/ForkExample.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api.examples.fork; 17 | 18 | import com.asyncj.core.api.ActorManager; 19 | import org.junit.Test; 20 | 21 | /** 22 | * User: APOPOV 23 | * Date: 05.10.13 24 | */ 25 | public class ForkExample { 26 | 27 | @Test 28 | public void testPingPong() { 29 | 30 | ActorManager actorManager = new ActorManager(); 31 | 32 | int n = 10000000; 33 | Actor1 actor1 = actorManager.createActor(new Actor1Impl(n)); 34 | 35 | actor1.startPings(actorManager, n); 36 | 37 | try { 38 | Thread.currentThread().join(); 39 | } catch (InterruptedException e) { 40 | throw new RuntimeException(e); 41 | } 42 | } 43 | 44 | public interface Actor1 { 45 | void startPings(ActorManager actorManager, int n); 46 | void pong(Actor2 actor2, String s); 47 | } 48 | 49 | public interface Actor2 { 50 | void ping(Actor1 actor1, int count); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /api/src/test/java/com/asyncj/core/api/examples/forkjoin/Actor1Impl.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api.examples.forkjoin; 17 | 18 | import com.asyncj.core.api.ActorManager; 19 | 20 | class Actor1Impl implements ForkJoinExample.Actor1 { 21 | 22 | private final int workLoad; 23 | private int n; 24 | private int count = 0; 25 | 26 | private ForkJoinExample.Actor1 parentActor1; 27 | private int incTimes; 28 | 29 | public Actor1Impl(int n, ForkJoinExample.Actor1 parentActor1, int workLoad) { 30 | this.n = n; 31 | this.parentActor1 = parentActor1; 32 | this.workLoad = workLoad; 33 | } 34 | 35 | public void pong(ForkJoinExample.Actor2 actor2, String s) { 36 | count++; 37 | 38 | if (count < n) { 39 | if (count % 100000 == 0) 40 | System.out.println(count + " pings from - " + s); 41 | actor2.ping(this, count); 42 | } 43 | else { 44 | System.out.println("final count = " + count); 45 | if (parentActor1 != null) { 46 | parentActor1.incCount(count); 47 | } 48 | } 49 | } 50 | 51 | @Override 52 | public void incCount(int count) { 53 | incTimes++; 54 | this.count += count; 55 | System.out.println("sub count = " + this.count); 56 | if (incTimes >= 5 && parentActor1 != null) { 57 | parentActor1.incCount(this.count); 58 | } 59 | } 60 | 61 | @Override 62 | public void startPings(ActorManager actorManager, int m) { 63 | if (m < workLoad) { 64 | ForkJoinExample.Actor2 actor2 = actorManager.createActor(new Actor2Impl()); 65 | actor2.ping(this, m); 66 | } 67 | else { 68 | int m1 = m / 5; 69 | int m2 = m - m1 * 4; 70 | ForkJoinExample.Actor1 thisActor = actorManager.getReference(this); 71 | 72 | ForkJoinExample.Actor1 actorA = actorManager.createActor(new Actor1Impl(m1, thisActor, workLoad)); 73 | ForkJoinExample.Actor1 actorB = actorManager.createActor(new Actor1Impl(m1, thisActor, workLoad)); 74 | ForkJoinExample.Actor1 actorC = actorManager.createActor(new Actor1Impl(m1, thisActor, workLoad)); 75 | ForkJoinExample.Actor1 actorD = actorManager.createActor(new Actor1Impl(m1, thisActor, workLoad)); 76 | ForkJoinExample.Actor1 actorE = actorManager.createActor(new Actor1Impl(m2, thisActor, workLoad)); 77 | actorA.startPings(actorManager, m1); 78 | actorB.startPings(actorManager, m1); 79 | actorC.startPings(actorManager, m1); 80 | actorD.startPings(actorManager, m1); 81 | actorE.startPings(actorManager, m2); 82 | } 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /api/src/test/java/com/asyncj/core/api/examples/forkjoin/Actor2Impl.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api.examples.forkjoin; 17 | 18 | import java.lang.reflect.Proxy; 19 | 20 | class Actor2Impl implements ForkJoinExample.Actor2 { 21 | 22 | public void ping(ForkJoinExample.Actor1 actor1, int count) { 23 | if (count % 100000 == 0) 24 | System.out.println(count + " pongs"); 25 | if (!(actor1 instanceof Proxy)) { 26 | throw new RuntimeException("Should be a proxy"); 27 | } 28 | actor1.pong(this, this.toString()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /api/src/test/java/com/asyncj/core/api/examples/forkjoin/ForkJoinExample.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api.examples.forkjoin; 17 | 18 | import com.asyncj.core.api.ActorManager; 19 | import org.junit.Test; 20 | 21 | /** 22 | * User: APOPOV 23 | * Date: 05.10.13 24 | */ 25 | public class ForkJoinExample { 26 | 27 | @Test 28 | public void testPingPong() { 29 | 30 | ActorManager actorManager = new ActorManager(); 31 | 32 | final long startTime = System.currentTimeMillis(); 33 | 34 | int n = 10000000; 35 | int workLoad = n / Runtime.getRuntime().availableProcessors(); 36 | Actor1 actor1 = actorManager.createActor(new Actor1Impl(n, new Actor1() { 37 | @Override 38 | public void startPings(ActorManager actorManager, int n) { 39 | 40 | } 41 | 42 | @Override 43 | public void pong(Actor2 actor2, String s) { 44 | 45 | } 46 | 47 | @Override 48 | public void incCount(int count) { 49 | long endTime = System.currentTimeMillis(); 50 | System.out.println("super mega total count = " + count + ". In " + (endTime - startTime)/1000 + " seconds"); 51 | 52 | } 53 | }, workLoad)); 54 | 55 | actor1.startPings(actorManager, n); 56 | 57 | try { 58 | Thread.currentThread().join(); 59 | } catch (InterruptedException e) { 60 | throw new RuntimeException(e); 61 | } 62 | } 63 | 64 | public interface Actor1 { 65 | void startPings(ActorManager actorManager, int n); 66 | void pong(Actor2 actor2, String s); 67 | 68 | void incCount(int count); 69 | } 70 | 71 | public interface Actor2 { 72 | void ping(Actor1 actor1, int count); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /api/src/test/java/com/asyncj/core/api/examples/pingpong/Actor1Impl.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api.examples.pingpong; 17 | 18 | 19 | import com.asyncj.core.api.ActorManager; 20 | 21 | class Actor1Impl implements PingPongExample.Actor1 { 22 | 23 | int n; 24 | private ActorManager actorManager; 25 | int count = 0; 26 | final long startTime; 27 | 28 | 29 | public Actor1Impl(int i, ActorManager actorManager) { 30 | this.n = i; 31 | this.actorManager = actorManager; 32 | startTime = System.currentTimeMillis(); 33 | } 34 | 35 | public void pong(PingPongExample.Actor2 actor2, String s) { 36 | count++; 37 | if (count % 100000 == 0) 38 | System.out.println(count + " pings from - " + s); 39 | 40 | if (count < n) { 41 | actor2.ping(this, count); 42 | } 43 | else { 44 | long endTime = System.currentTimeMillis(); 45 | System.out.println("super mega total count = " + count + ". In " + (endTime - startTime)/1000 + " seconds"); 46 | 47 | // how to send a final message? 48 | actorManager.unblockResult(this); 49 | } 50 | } 51 | 52 | @Override 53 | public Integer getCount() { 54 | return count; 55 | } 56 | 57 | public void startPings(PingPongExample.Actor2 actor2) { 58 | count++; 59 | actor2.ping(this, count); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /api/src/test/java/com/asyncj/core/api/examples/pingpong/Actor2Impl.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api.examples.pingpong; 17 | 18 | class Actor2Impl implements PingPongExample.Actor2 { 19 | 20 | public void ping(PingPongExample.Actor1 actor1, int count) { 21 | if (count % 100000 == 0) 22 | System.out.println(count + " pongs"); 23 | actor1.pong(this, this.toString()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /api/src/test/java/com/asyncj/core/api/examples/pingpong/PingPongExample.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api.examples.pingpong; 17 | 18 | import com.asyncj.core.api.ActorManager; 19 | import org.junit.Test; 20 | 21 | import java.util.Collection; 22 | import java.util.List; 23 | 24 | /** 25 | * User: APOPOV 26 | * Date: 05.10.13 27 | */ 28 | public class PingPongExample { 29 | 30 | @Test 31 | public void testPingPong() { 32 | 33 | ActorManager actorManager = new ActorManager(); 34 | 35 | int pNumber = Runtime.getRuntime().availableProcessors(); 36 | 37 | Actor1 actor1 = actorManager.createActor(new Actor1Impl(1000000, actorManager)); 38 | List actor2Array = actorManager.createActors(new Actor2Impl(), pNumber); 39 | 40 | for (Actor2 actor2 : actor2Array) { 41 | actor1.startPings(actor2); 42 | } 43 | 44 | //this method call should block the current thread 45 | // and the Actor proxy should return the result when 46 | // it will be available after processing all messages passed to actor1... 47 | 48 | Integer count = actor1.getCount(); 49 | 50 | // if the actor returns as a result another actor then the actor manager will return an 51 | // empty proxy of an actor 52 | 53 | System.out.println("final count = " + count); 54 | } 55 | 56 | public interface Actor1 { 57 | 58 | void startPings(Actor2 actor2); 59 | 60 | void pong(Actor2 actor2, String s); 61 | 62 | Integer getCount(); 63 | } 64 | 65 | public interface Actor2 { 66 | 67 | void ping(Actor1 actor1, int count); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /api/src/test/java/com/asyncj/core/api/examples/plainjava/Actor1Impl.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api.examples.plainjava; 17 | 18 | 19 | class Actor1Impl implements PlainJavaExample.Actor1 { 20 | 21 | int n; 22 | int count = 0; 23 | final long startTime; 24 | 25 | 26 | public Actor1Impl(int i) { 27 | this.n = i; 28 | 29 | startTime = System.currentTimeMillis(); 30 | } 31 | 32 | public void pong(PlainJavaExample.Actor2 actor2, String s) { 33 | count++; 34 | if (count < n) { 35 | if (count % 100000 == 0) 36 | System.out.println(count + " pings from - " + s); 37 | actor2.ping(this, count); 38 | } 39 | else { 40 | long endTime = System.currentTimeMillis(); 41 | System.out.println("super mega total count = " + count + ". In " + (endTime - startTime)/1000 + " seconds"); 42 | } 43 | } 44 | 45 | public void startPings(PlainJavaExample.Actor2 actor2) { 46 | count++; 47 | actor2.ping(this, count); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /api/src/test/java/com/asyncj/core/api/examples/plainjava/Actor2Impl.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api.examples.plainjava; 17 | 18 | class Actor2Impl implements PlainJavaExample.Actor2 { 19 | 20 | public void ping(PlainJavaExample.Actor1 actor1, int count) { 21 | if (count % 100000 == 0) 22 | System.out.println(count + " pongs"); 23 | actor1.pong(this, this.toString()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /api/src/test/java/com/asyncj/core/api/examples/plainjava/PlainJavaExample.java: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2013 Aliaksei Papou 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.asyncj.core.api.examples.plainjava; 17 | 18 | import org.junit.Test; 19 | 20 | /** 21 | * This example uses plain Java calls between actors and it will produce a stack overflow exception. 22 | * Such as actors calls each other recursively in one execution thread. 23 | * User: APOPOV 24 | * Date: 05.10.13 25 | */ 26 | public class PlainJavaExample { 27 | 28 | @Test 29 | public void testPingPong() { 30 | 31 | Actor1 actor1 = new Actor1Impl(10000000); 32 | 33 | Actor2[] actor2Array = new Actor2[Runtime.getRuntime().availableProcessors()]; 34 | 35 | for (int i = 0; i < actor2Array.length; i++) { 36 | actor2Array[i] = new Actor2Impl(); 37 | } 38 | 39 | for (int i = 0; i < actor2Array.length; i++) { 40 | actor1.startPings(actor2Array[i]); 41 | } 42 | 43 | try { 44 | Thread.currentThread().join(); 45 | } catch (InterruptedException e) { 46 | throw new RuntimeException(e); 47 | } 48 | } 49 | 50 | public interface Actor1 { 51 | void startPings(Actor2 actor2); 52 | void pong(Actor2 actor2, String s); 53 | } 54 | 55 | public interface Actor2 { 56 | void ping(Actor1 actor1, int count); 57 | } 58 | 59 | } 60 | --------------------------------------------------------------------------------