aspose file tools*
The moose likes Threads and Synchronization and the fly likes How to implement a non blocking Callback functionality. Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "How to implement a non blocking Callback functionality." Watch "How to implement a non blocking Callback functionality." New topic
Author

How to implement a non blocking Callback functionality.

Heena Agarwal
Ranch Hand

Joined: Dec 25, 2013
Posts: 261
    
    4
Hi,

A couple of days back, someone had asked a similar question in Java In General forum ( http://www.coderanch.com/t/629201/java/java/Threading ).

While answering a similar question here, Erickson suggested that we can implement a Callback interface if we want our Executor to be notified without blocking that a task has completed. I liked his suggestion of implementing a Callback. But I've also had a couple of questions regarding how I would go about it if I had to implement a similar functionality. So for learning, I came up with a similar requirement of my own. I also didn't want to steal this topic from the OP in JIG forum cause my requirement ( it's just for learning purpose, hence I will understand if you'd suggest that a couple of things I'm going to say aren't practical in the real applications ) might not be exactly his/her requirement.

So let us say that my requirement is as follows.

Have a thread spawn a couple of threads. Let us refer to the first thread as the parent thread and the threads it spawns as child threads. So I want the parent thread to get a notification when a child thread completes and to also get a notification when there's an exception in the child thread. Yes, I could have used a Callable implementation but we know that the get method is a blocking method. So I have utilized Erickson's suggestion to come up with an implementation of a Callback.

I'm not sure if what I'm doing is right. I think there are a couple of things that aren't good about my solution. I will mention them later. But for now, here is what I have.



I don't like the idea of passing a reference of the ParentThread to each of the ChildThread. How do I rectify this part? Do you see other possible problems with what I have tried?

If so, would you like to part with a hint or suggestion to go about it? Or is there a better approach?

Thanks for going through this post. It's too long, I know.

Edit : The output of the above code is as follows.

name = thread0 and i = 0
name = thread0 and i = 1
name = thread2 and i = 0
name = thread2 and i = 1
name = thread1 and i = 0
name = thread4 and i = 0
name = thread4 and i = 1
name = thread2 and i = 2
name = thread2 and i = 3
name = thread2 and i = 4
name = thread2 and i = 5
name = thread0 and i = 2
name = thread0 and i = 3
name = thread0 and i = 4
name = thread0 and i = 5
name = thread0 and i = 6
name = thread0 and i = 7
name = thread0 and i = 8
name = thread3 and i = 0
name = thread0 and i = 9
name = thread7 and i = 0
name = thread7 and i = 1
name = thread2 and i = 6
name = thread4 and i = 2
name = thread4 and i = 3
name = thread9 and i = 0
Exception in thread thread6 at time 1393247699422
name = thread5 and i = 0
name = thread5 and i = 1
name = thread5 and i = 2
name = thread5 and i = 3
name = thread5 and i = 4
name = thread5 and i = 5
name = thread1 and i = 1
name = thread1 and i = 2
name = thread1 and i = 3
name = thread1 and i = 4
name = thread1 and i = 5
name = thread1 and i = 6
name = thread1 and i = 7
name = thread1 and i = 8
name = thread1 and i = 9
Thread thread1 completed at time 1393247699423
Exception in thread thread5 at time 1393247699423
name = thread9 and i = 1
name = thread4 and i = 4
name = thread2 and i = 7
name = thread2 and i = 8
name = thread2 and i = 9
Thread thread2 completed at time 1393247699424
name = thread8 and i = 0
name = thread7 and i = 2
name = thread7 and i = 3
name = thread7 and i = 4
Thread thread0 completed at time 1393247699422
name = thread3 and i = 1
name = thread7 and i = 5
name = thread8 and i = 1
name = thread4 and i = 5
name = thread9 and i = 2
name = thread4 and i = 6
name = thread8 and i = 2
name = thread7 and i = 6
name = thread3 and i = 2
name = thread7 and i = 7
name = thread8 and i = 3
name = thread4 and i = 7
name = thread9 and i = 3
name = thread4 and i = 8
name = thread8 and i = 4
name = thread7 and i = 8
name = thread3 and i = 3
name = thread7 and i = 9
name = thread8 and i = 5
name = thread4 and i = 9
name = thread9 and i = 4
Thread thread4 completed at time 1393247699425
name = thread8 and i = 6
Thread thread7 completed at time 1393247699425
name = thread3 and i = 4
name = thread8 and i = 7
name = thread9 and i = 5
name = thread8 and i = 8
name = thread3 and i = 5
name = thread8 and i = 9
name = thread9 and i = 6
Thread thread8 completed at time 1393247699425
name = thread3 and i = 6
name = thread9 and i = 7
name = thread3 and i = 7
name = thread9 and i = 8
name = thread3 and i = 8
name = thread9 and i = 9
name = thread3 and i = 9
Thread thread9 completed at time 1393247699426
Thread thread3 completed at time 1393247699426


[Moderator Edit : Edited to correct the attribution of referenced design of implementing a Callback to its original source. Only attribution parts have been edited.]
Roger Sterling
Ranch Hand

Joined: Apr 06, 2012
Posts: 426

One construct that I found very useful is a Singleton. You can create a HashMap there and store various things, such as references to other threads, including the parent thread, and it's callback address. You can also easily implement JMX and view the life of your application from jconsole. You can even use jconsole to submit various inputs to various threads and see how your application responds to these and view the passing of various events through your numerous thread callbacks.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3647
    
  17

I would *really* discourage you from using a singleton, or other static data, especially in a multi-threaded environment. Your code becomes completely non-deterministic.

I don't understand why you want to implement a callback mechanism, and then not use it. What reason could you have not to want to pass your callback to the children?
Heena Agarwal
Ranch Hand

Joined: Dec 25, 2013
Posts: 261
    
    4
First, thanks for your responses.

Stephan van Hulst wrote:
I don't understand why you want to implement a callback mechanism, and then not use it. What reason could you have not to want to pass your callback to the children?


I'm *technically* using the callback ( I'm printing that the thread completed or there was an exception ). Since this is for learning, that's all I'm using it for, but I understand it could be used for many other things.

For not passing the callback to the children, I don't have any reasons as such. I just wanted to explore if there is another pattern that could be used along with this basic design to make this design better. More along the lines of not having to pass the this reference directly to the child threads because I thought that the child thread can now invoke the run method of the parentThread manually also or it can use it in ways it is not supposed to use, but I'm probably just thinking in the wrong direction?
Roger Sterling
Ranch Hand

Joined: Apr 06, 2012
Posts: 426

Stephan van Hulst wrote:I would *really* discourage you from using a singleton, or other static data, especially in a multi-threaded environment. Your code becomes completely non-deterministic.

I don't understand why you want to implement a callback mechanism, and then not use it. What reason could you have not to want to pass your callback to the children?


Your argument is so totally bogus. Singletons are used in many major software distributions, not the least of which are Application Servers (WAS) and Enterprise Service Buses (IIB).

What do you mean by "non-deterministic"? Speak English.

Singletons are containers for items that you only want to store once, for example, when you want to use JMX and store JMX MxBeans that represent various things about your application. These items are far from "static" as you allude to. They are very dynamic, hence the need for a Singleton pattern.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3647
    
  17

Roger Sterling wrote:Your argument is so totally bogus. Singletons are used in many major software distributions, not the least of which are Application Servers (WAS) and Enterprise Service Buses (IIB).


Aye, and this week I read an article about Apple breaking TLS. The fact that some major players do certain things, does not make them good ideas.

What do you mean by "non-deterministic"? Speak English.


Your application can no longer guarantee that important invariants will hold. As soon as you introduce mutable data that's globally accessible, I can introduce a piece of code that will break all assumptions you make about that data. This is not a trivial matter; how many applications need security updates because plugins are able to break your things?

Singletons are containers for items that you only want to store once, for example, when you want to use JMX and store JMX MxBeans that represent various things about your application. These items are far from "static" as you allude to. They are very dynamic, hence the need for a Singleton pattern.


By static I mean the Java definition of static. I'm referring to global data. And if your data is dynamic in nature then especially it's a bad idea to have it globally accessible. Use dependency injection instead. Much safer, much easier to debug, much clearer.
Roger Sterling
Ranch Hand

Joined: Apr 06, 2012
Posts: 426

Ok, your discussion does represent valid concepts. Given your view of the world then, where would you put your MxBeans that need to be globally accessed ?

http://docs.oracle.com/javase/7/docs/api/javax/management/MXBean.html

http://docs.oracle.com/javase/tutorial/jmx/mbeans/mxbeans.html








Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3647
    
  17

Let me have a look, I will get back to you.
Jayesh A Lalwani
Bartender

Joined: Jan 17, 2008
Posts: 2393
    
  28

I would like to know what are you going to be doing in the callback? Remember that technically, your callback is executing in the child thread, even though in your case it's implemented in the Parent Thread class. I know it's confusing, because you have named your classes badlyBtw,.. this is the reason I don't like calling classes that has implementation of some work to be done as threads. They are not threads, they are tasks. So, if you callback implementation is doing something that is not thread safe, you will need to add synchronization in your callback, which means that your child threads will start blocking each other. Depending on how heavy your callback mechanism is, you might lose any advantage that you might gain by parallelizing your processing

Yes, Callback might work but only for a limited number of use cases which require the Callback to be a no-op. The major problem with callback, IMO, is not what you are worried about; ie; the child thread knowing about the parent thread. The major problem is that it's not scalable. The entire point of doing scalable design is to remove/reduce synchronization blocks, but the Callback pattern forces your to introduce big synchronization blocks.


AN alternate pattern that I would suggest is Event Loop. BTW, this pattern is the pattern that NIO uses. The basic idea in an event loop is that each thread has a queue in front of it. Anyone can post a message into the queue, and the thread will pick up the message and do what it needs to do. Threads don;t communicate to each other directly. They communicate by posting messages into the event loop. You can even have multiple threads looking at the same event loop queue. However, at no time will any thread read from more than one event loop queue.
In your case, you will have a parent thread and one or more child threads. The parent thread has an event loop queue, and all the child threads are sharing the same event loop queue. When your main method wants to run a task, it posts an event into the parent thread's queue. Parent thread wakes up determines that it wants child threads to run 10 tasks, and posts 10 messages to the child queue. The child threads wake up, execute the task, and on completion/error post a message into the parent's event queue. The parent picks up the message and processes it

Heena Agarwal
Ranch Hand

Joined: Dec 25, 2013
Posts: 261
    
    4
Hi Jayesh.

I thought that this was a special case of a non blocking executor/parent task implementation that needed to have independent and non interfering tasks running in parallel with a callback functionality. But, after reading your response I realized the problems with my implementation. I agree that the notifyCompletion and notifyException methods would need synchronization and the System time also will not be accurate. The child tasks should send the time as a parameter or something. So now that I think of synchronization, I understand that what I have coded is not scalable and can only cater to a small number of cases.

As for the class names, I agree that the objects of those classes are tasks and hence the classes should be named accordingly. This part is easy to fix. I'll fix it.

I will work on the Event Loop design. It looks far better for now. Not sure if it will be able to handle the exception notifications but while working on it, I might find out that it's possible. So I'm working on it.

Thanks for responding.


Heena Agarwal
Ranch Hand

Joined: Dec 25, 2013
Posts: 261
    
    4
Actually on second thoughts, if we just add the required synchronization
in the callback methods ( and we may not need to synchronize those entire methods )
and if we have a case in which task.run() is going to take far more
time when compared to the critical parts of the callback methods,
we can still get a fair amount of concurrency.

I understand though that this approach has limited application.
Jayesh A Lalwani
Bartender

Joined: Jan 17, 2008
Posts: 2393
    
  28

Yes, but in that case why would you even put that code in the ParentThread/task. Why not just put that code in the ChildThread/Task? Ideally, you should have the code that updates the state of your application wrapped in it's own Data Access layer, and your Thread/task should really just have the business logic that calls the relevant method in the data access layer. SO, if you don't mind updating the state of the parent task in the child thread, why not just call the relevant methods right in the child task?

To my mind, when you are talking about multi threading, it makes more sense to put business logic that is going to be called in the same thread in the same module. It just gets very confusing if you have to keep track of which threads might call individual methods. Multithreading is hard enough as it is. You don't need to make it harder by having to remember which threads call what. It's too much of a spaghetti for me

Another design pattern that you might want to think about is Decorator. If all you want to do is do some setup/cleanup before/after each task, and you don't want the task to be dependent on the setup/cleanup, then you can just implement a Decorator that wraps your tasks. Decorator is very simple on a Runnable. If you are using Spring, you might even be able to just implement some annotations

Event loop is harder to implement than a Decorator. But, if you do go the Event Loop route, you might want to look at ExecutorService. You can easily implement an Event Loop using ExecutorService. Just set the queue to be unbounded
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3647
    
  17

Roger, I'm not too familiar with JMX, but to me it seems you simply register MxBean instances with an MBeanServer. I don't really see how they have to be singleton.
Roger Sterling
Ranch Hand

Joined: Apr 06, 2012
Posts: 426

Stephan van Hulst wrote:Roger, I'm not too familiar with JMX, but to me it seems you simply register MxBean instances with an MBeanServer. I don't really see how they have to be singleton.


No one is saying you "have to" use anything.

I suggested to the OP the use of the Singleton pattern, and you came out flat against it, not even knowing anything about JMX or how Singletons are used in that context.

A Singleton is an excellent option for using MXBeans: it provides auto-registration of the MxBeans to the MBeanServer and manages redeployment of the same code, so that the MxBeans do not have multiple duplicate registrations in place at the MBeanServer.

A Singleton offers the ability to cache various diagnostic data about your application program, which can be exposed as a Web Service resource, RESTful or not.

At runtime, a Singleton implementation can be injected, that is, resolved using an IOC container and be replaced with an actual implementation class instance. This way, there is no hard-coded dependency between the object that depends on the Singleton and the actual implementation of the Singleton interface.


Before you jump the gun next time, why not thoughtfully consider what is being talked about. Your opposition has some valid points, especially if people misuse the Singleton pattern, but don't listen to all the hype from people who have no skill at using Singletons. Skillful software development is not for people with no experience or lack of imagination. It is true the Singleton pattern is easily abused, but at the same time, some useful things can be done with it.

The next time you are using your favorite software package and you make a call like "getInstance", you are in fact using the very thing you swore against. Don't be so adamant against something , especially when you have little or no actual experience using same.

Novices with no belief, imagination, or desire to excel should shy away from programming patterns that require skill. Like the carnival booth where you toss a nickel onto a plate to win a prize, if you are not good at tossing nickels, or don't realize that licking the nickel before you toss it will dampen its bounce, then you should not be playing that game to begin with. Software development takes skill to do things in an absolutely perfect way, knowledge to know when to do or not do, imagination to think of things that can be done, even if they never have been done that way before, and lots of practice. If at first you don't succeed, try try again. It may take twenty failures before you finally get the elevated concept of a pattern like a Singleton. But once you discover what it can do, you may find your self using it more often than not. Most of your favorite application packages do, and there is a reason for that.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3647
    
  17

Roger Sterling wrote:I suggested to the OP the use of the Singleton pattern, and you came out flat against it, not even knowing anything about JMX or how Singletons are used in that context.

Because regardless of what technology uses singletons, it is ALWAYS a bad idea to have mutable singletons for business logic.

A Singleton is an excellent option for using MXBeans: it provides auto-registration of the MxBeans to the MBeanServer and manages redeployment of the same code, so that the MxBeans do not have multiple duplicate registrations in place at the MBeanServer.

At the cost of making that data completely unreliable.

A Singleton offers the ability to cache various diagnostic data about your application program, which can be exposed as a Web Service resource, RESTful or not.
At runtime, a Singleton implementation can be injected, that is, resolved using an IOC container and be replaced with an actual implementation class instance. This way, there is no hard-coded dependency between the object that depends on the Singleton and the actual implementation of the Singleton interface.

I don't really see how any of this makes singleton necessary, or mitigates its flaws. Inversion of control works perfectly without concrete implementations having to be singleton.

The next time you are using your favorite software package and you make a call like "getInstance", you are in fact using the very thing you swore against.

Not true. You can use a method called getInstance() to get a default factory implementation from a service loader. A factory does not represent data. It generates services which by their nature are not globally accessible.

Don't be so adamant against something , especially when you have little or no actual experience using same.

Novices with no belief, imagination, or desire to excel should shy away from programming patterns that require skill. Like the carnival booth where you toss a nickel onto a plate to win a prize, if you are not good at tossing nickels, or don't realize that licking the nickel before you toss it will dampen its bounce, then you should not be playing that game to begin with. Software development takes skill to do things in an absolutely perfect way, knowledge to know when to do or not do, imagination to think of things that can be done, even if they never have been done that way before, and lots of practice. If at first you don't succeed, try try again. It may take twenty failures before you finally get the elevated concept of a pattern like a Singleton. But once you discover what it can do, you may find your self using it more often than not. Most of your favorite application packages do, and there is a reason for that.

This was completely uncalled for. You have absolutely no reason to imply I'm a "novice", and I find the tone you address me with very insulting. I also don't need to have experience with a specific technology like JMX, to reason that some usages it apparently supports, aren't a good idea. I don't have to be a carpenter to know it's generally not a good idea to use a saw to hit nails with.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: How to implement a non blocking Callback functionality.