laforge49 / jactor Goto Github PK
View Code? Open in Web Editor NEWActors for Java
Actors for Java
I am very concerned that when creating an anonymous subclass of Binding, it is too easy to do unsafe things like call send from within acceptRequest. I find myself doing this, so I know it will happen. And the code seems to work, making it especially dangerous.
My solution is to pass internals in the processRequest method of Binding and to restrict the protected API of JBActor and Component. Methods that are unsafe to call in acceptRequest will then only be accessible via the internals parameter on processRequest.
It is a bit ugly, as now you will need to do a internals.send instead of just send. But it will eliminate a bunch of thread safety issues, so I think is is worth it.
Go to https://github.com/laforge49/JActor/blob/master/src/test/java/org/agilewiki/jactor/multithreading/ResponsePrinterTest.java and look at the todo in test 4. The (commented out) code causes the test to hang.
This is the first time I've tested sending multiple requests from different threads to a mailbox. And it doesn't work. Fortunately it continues to fail after adding print statements, so it should not be a really hard bug to track down, but the bug is likely located in some of the more difficult code.
Add a findParent method to JLPCActor:
public TargetActor findParent(Class parentClass);
Concurrent requests can now be handled by either a simple method call, or a call to the parent which is an instanceof a given class.
Working on TupleTest in the JID project when it became evident that there is a bug in JActor--DefineActorType should be an initialization request.
Some requests should be fully atomic, i.e. transactional. For this we need an atomic request, atomic binding and an atomic component.
JBActor calls the open(Internals) method the first time a non-initialization method is received. This is not thread safe, so we have a choice between making open an explicit request or using a synchronization lock. An ugly choice.
JActor does not use locks and that's important for performance, so we need to make open an initialization request. That's a big change and not a very good one, as it adds a line of code everywhere an actor is created. But necessary, methinks.
Initialization is always such a mess.
We should drop the process method from the RD class--it is only there for historical reasons.
A duplicate asynchronous response was throwing a null pointer exception rather than checking to see if the request was still active.
Statement:
Consider the below code :
// Please refer org.agilewiki.jactor.basics.Test5 for the complete program
MailboxFactory mf = getMailboxFactory();
Actor5 a = new Actor5();
a.initialize(mf.createAsyncMailbox());
Actor5 b = new Actor5();
b.initialize(mf.createAsyncMailbox());
Actor5 c = new Actor5();
c.initialize(mf.createAsyncMailbox());
a.delay = 10;
c.delay = 10;
a.delay = 10;
final long t0 = System.currentTimeMillis();
RP<Object> rc = new RP<Object>() {
int c = 3;
@Override
public void processResponse(Object response) throws Exception {
c -= 1;
if (c == 0) {
long t1 = System.currentTimeMillis();
System.out.println("Time taken-->" + (t1 - t0));
rp.processResponse((t1 - t0) <= 30);
}
}
};
Delay.req.send(this, a, rc);
Delay.req.send(this, b, rc);
Delay.req.send(this, c, rc);
The timing test will yield best output for the following definition of MailboxFactory-
MailboxFactory mailboxFactory = JAMailboxFactory.newMailboxFactory(3); // creates 3 threads for 3 async mailboxes
Whereas, with 1 or 2 threads (JAMailboxFactory.newMailboxFactory(1) or JAMailboxFactory.newMailboxFactory(2)), it is not going yield optimal output.
Problem :
End user's program may be dynamic in nature. How about making the MailboxFactory initialization intelligent, so that based on a given problem it will spawn optimal number of threads automatically.
If you send a synchronous request rather than doing a call, and that request raises an exception, the exception is not handled properly.
While converting everything from components to JLPCActors, a bug was found in org.agilewiki.jactor.multithreadingTest.exceptions.ExceptionTest. Apparently the exception handler set in test case 4 is not being cleared in test case 5. (For the moment, test case 5 has been commented out.)
Eliminate the request and response wrappers by moving the code into the base Request class and by creating a base Response class.
TargetActor is seemingly unnecessary. It was a device introduced to get Request to compile correctly. There may be a better way, especially considering the high-visibility of TargetActor in the API.
It is time for JAThreadManager to become a full blown ExecutorService. This will allow the JAMailboxFactory constructor to take any ExecutorService as an argument. But more importantly, it will allow greater use of JAThreadManager.
as the title.
A small change to JAEventQueue should give us much better timings. Here's the code that needs improving:
public boolean acquireControl(EventQueue<E> eventQueue) {
if (atomicControl.compareAndSet(null, eventQueue.getController())) {
notEmpty = false;
return true;
}
return false;
}
We need to add a faster check before the if statement:
public boolean acquireControl(EventQueue<E> eventQueue) {
if (atomicConttrol.get() != null) ||
atomicControl.compareAndSet(null, eventQueue.getController()) {
notEmpty = false;
return true;
}
return false;
}
We may be able to simplify things...
public interface Actor {
Mailbox mailbox();
Actor parent();
}
public class JLPCActor extends Actor {
public final Mailbox mailbox;
public final Actor parent;
public Mailbox mailbox() {
return mailbox;
}
public Actor parent() {
return parent;
}
public JLPCActor(Mailbox mailbox, Actor parent) {
this.mailbox = mailbox;
this.parent = parent;
}
}
The project contains a lot of unit tests, but no benchmarks supplied. As a result, it is hard to make sure the library is as fast as claimed.
Hi,
Looks to me we could be able to reject request after timeout?
Thanks
Julius
The NBLock component will have two requests, Begin and End. Begin requests are added to a queue; End requests pop the queue.
If the queue is empty when a Begin request is received, it gets an immediate response. Otherwise it receives a response when the queue is popped and the Begin request is now on top.
To use the NBLock component, you send a Begin request (with a callback). Once the callback is invoked you have exclusive access to some resource, but when done you need to send an End request to free up the resource. Note that no threads are blocked while the response to a begin request is pending.
There is no link to examples using this library in the main page. Wiki with some code samples would be very helpful.
Lets deprecate JLPCActor.processRequest while creating a non-abstract Request.processRequest method that calls it. New code can override Request.processRequest instead of JLPCActor.processRequest.
Hi,
The JLPCAtor use system.out.println to print the exception message, it is not so convenience to figure out where the exception is from. it might use logging like slf4j.
Thanks
Julius
hi,laforge49
I'm new to Jactor,I got code,and run the test ,It is fast.I read your document,but can not find a right way to use in my web app.
my web app is very simple,user input a task,every task run 10-100 second.I write a unit test such as blow
public class TaskTest {
//queuque to save taskids
LinkedBlockingQueue taskqueque=new LinkedBlockingQueue();
//flag,stop taskserver
boolean stop=false;
private ExecutorService taskExecutor= Executors.newFixedThreadPool(5);
@Before
public void setUp() throws Exception {
//create 5 taks server
for (int i = 0; i < 5; i++) {
taskExecutor.submit( new Taskserver());
}
}
@Test
public void test() {
int times=new Random().nextInt(50);
System.out.println("run "+times+" tasks");
for (int i = 0; i <times; i++) {
//add new task to queque
taskqueque.add(String.valueOf(i));
}
while(!taskqueque.isEmpty());
stop=true;
System.out.println("test over");
}
class Taskserver implements Runnable{
@Override
public void run() {
while(!stop){
try {
String taskid=taskqueque.take();
//sleep some times,simulate db read write
Thread.sleep(1000*new Random().nextInt(10));
System.out.println("work over task "+taskid+" at thread"+Thread.currentThread().getName() );
} catch (InterruptedException e) {
}
}
}
}
}
can you give me a sample how to use jactor in this class? thank you very much.
https://github.com/anirbanbhattacharjee/jactor-in-action, presently has only one asynchronous actor related example. Add some more asynchronous actor examples.
One more interesting thing may, doing something like remote actors(http://akka.io/) which presently AKKA does.
The moved method on Request<RETURN_RESULT, TARGET_ACTOR> would be
public abstract void processRequest(TARGET_ACTOR targetActor, RP<RETURN_RESULT> rp) throws Exception;
By moving this method, we no longer need to examine the class of the Request.
Synchronous requests should be handled by method calls.
JACTOR api presently doesn't have an executor service. Pivotal point of present architecture is the JAThreadManager class. This can be refactored and converted into a high performance executor service. On the other hand end users should be able to plug and play their own executor service too.
At a number of places in the codebase ==
is used to compare classes for equality, which is both slow and incorrect. It is incorrect because it wouldn't work with proxies where a new proxy sub-class is created at runtime. Examples: CGLIB proxy, JVM proxy, Spring-AOP integration etc.
A possible fix is to use instanceof
where the exact reference class is known beforehand, or to use class1.isAssignableFrom(class2)
. In a single-threaded experiment I did on a quad-core Intel i7 based Macbook Pro, I got the following mean numbers with a warmed JVM:
class1 == class2 | 2.747921 us
obj instanceof class1 | 2.743640 us
class1.isAssignableFrom(class2) | 2.741118 us
obj.getClass().isAssignableFrom(class2) | 2.781485 us
so less document , i want to learn the jactor but i have no lots of time to watch the code ,and the important,i 'm week of code skill,so it's hard to learn for me .
when i search the actor , out look of the akka and kilim, the jactor is the most come out ,i think it's the right thing i want.but i can't know how to use it .
see http://www.ibm.com/developerworks/library/j-javaactors/j-javaactors-pdf.pdf,it's what i want to see
could you write some project example?
Not really a big deal in the short term, but it would be great if the binaries and sources could be found in Maven central.
Another suggestion is to change the groupId to a fqn (org.jactor, etc) and have it lower-case, which seems to be a common Maven practice nowadays.
PS: Quite pleased to have come across this project.
JLPCActor should only have getters and setters for parent and mailbox. Requirements also need to be supported.
The async flag in JLPCMailbox should be moved to JAEventQueue.
The isAsync method in Mailbox should be moved to EventQueue.
Hi...
I'm new to JActor2. Is there any way to send a request to an actor without blocking? I don't need any return value and I don't want to wait till the processing ends. Something like kilim's Mailbox.putnb(...);
Thank you!
Factory is really a registry of ActorFactory's.
Factory => FactoryRegistry
JAFactory => JAFactoryRegistry
JAFactoryFactory => JAFactoryRegistryFactory.
In the JFile project, Deserializer throws an exception when an unrecognized transaction is encountered. The exception is lost and all you see is an obscure null pointer exception in JActor.
I think the problem is because of the use of 3 mailboxes, the first and third being async and the second being commandeered by the first. Deserializer is the third and, when the exception is passed back is when the error occurs.
By adding bounds to the request types of the binding classes we can constrain the types to what are reasonable. For example,
abstract public class InitializationMethodBinding<REQUEST_TYPE, RESPONSE_TYPE>
extends MethodBinding<REQUEST_TYPE, RESPONSE_TYPE> {
becomes
abstract public class InitializationMethodBinding
<REQUEST_TYPE extends InitializationRequest<RESPONSE_TYPE>, RESPONSE_TYPE>
extends MethodBinding<REQUEST_TYPE, RESPONSE_TYPE> {
This looks great: http://search.maven.org/#artifactdetails|org.apache.tapestry|plastic|5.3.2|jar
And here's a talk: http://www.infoq.com/presentations/Meta-Programming-Techniques-for-Java
I'm thinking this will come later, like JActor3. Unless someone else beats me to it--I've got a bunch of other things to do before JActor 3!
Comments?
--b
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.