Andre's Blog

20161028 Communication In CISystem Between Threads




My last blog post is 3 weeks ago.

Seems I have to post more often about what I am thinking than what I have implemented yet.

It guess it would be easier to follow me if I tell you my ideas before I show you my code and I could do this more often.

For me as a software developer it still feels funny to present an analysis or an idea which is not coded yet and maybe never becomes code, but I try to work on this.

This weekend I have visited Eike, which was really great! We had lots of fun and some really good discussions.

I also had time on the train rides for writing my blog and implementing an elaborate example for what has haunted me the last weeks :

How do threads communicate with each other?

So what did I do the last 3 weeks :

I had to bring some requirements and needs together :

  1. I wanted smaller code, which is easier to understand, I wanted to follow the Single-Responsibility-Principle (SRP)
  2. I had to find out how my threads will communicate with each other (CPP, OP)

Let's discuss this.

Single Responsibility Principle (SRP) And Separation Of Concerns (SoC)

My understanding of the Single Responsibility Principle is :

Every function or class should only do exactly one thing.

What does that mean?

For me it means, if a function does only do one thing but is still complex, a class should be implemented, which does the same what the function did, but which is a refactored version of it, a set of smaller functions, where every function does only one thing.

If this new class has more than 10 functions you should think about moving those functions, which have more in common with each other than with the other functions, to new classes.

What does this mean for the CISystem architecture?

One decision I made was to have an own class for every request and every response and to handle and execute them by the statemachine.

Then I remembered the requirement that every communication and action shall be logged. I don't want to mix concerns, I don't want to implement a logger part in every action to be handled. So I decided to have logger classes which take CIData object and log it. This way I also implement the segregation of concerns, because I have separated the code for actions from the code for logging by putting it into different classes.

The last question about logging was : How do I tell my software to write the CIData objects human readable into the log? The answer is, the objects must be added to a to-be-logged-list and some thread must check if there is something to log and do it.

Consumer Producer Problem

I have threads which collect information about new nodes in the network.

I have threads which create socket connections to these new nodes.

There could be a thread logging performed actions.

So some threads produce data in lists and some consume this data.

If these threads synchronize on the list, this solves the Consumer Producer Problem .

This looks like a solution how the threads can communicate with each other while they execute their run-loop.

Observer Pattern (OP)

The only thing I did not like about communicating only via lists was : When I have something to log, because a thread has put something into the to-be-logged-list, then the client has to poll this information, because it is synchronized on the list, at least this is my personal understanding of it.

I can introduce a sleep(1000), which would work, but which smells like a workaround, because I do not understand the situation yet.

And polling in general, to be honest, has become a little bit out-of-date as technique. When using git you would use a Git trigger and not have a Jenkins script polling for a change in your repo, yes?

Let's use the Observer Pattern, let's inform the logger that there is data.

Java provides the implementation for the Observable class, you just need to extend your own class with it. Then you implement the update function for those classes which implement the Observer interface.

But the notify function of the Observable class only informs the Observers about the change, while the Observers do ... what? Actively wait?

No, there is something missing.

I googled several times "java thread observer pattern", but did not find anything helpful.

I explained it to Eike, I said "What I need to find out is how to code an Observer thread waiting for a notification of an Observable thread". One minute later Eike had found this link :

There they explain the thread synchronization via the wait() and notifyAll() functions of the Object class.

The search phrase was "java thread wait example" and again it was clear : The computer does what you say, not what you want...

OK, so the Java class Object implements a mechanism to register some Observers to an object and the information produced by the server is : clients, wake up.

Combination of OP and CPP with wait and notify

After knowing how to prevent active waiting by using wait() and notify() the question was, how do I pass the data from the server thread to the client threads? Writing it to a global list or singleton automatically means new problems :

  1. you cannot write unit tests when using singletons
  2. you must come up with an idea for how to detect that an information is consumed to remove it from the list

I have decided to use the Observer Pattern implementation of Java for this, I use the notifyObservers(arg) function of the Observable class to pass the information direct into the update(arg) function of the clients. There the new information is added to a list member of the client. This happens in a synchronized block, so it will not be interrupted.

So at the end I am doing what I was starting with, I am using the Consumer Producer Pattern, because I want to decouple the threads and so I have no influence on the situation that the server can create new data before all clients have consumed the old data.

Exactly this was what I like about the Consumer Producer Pattern, it decouples the threads and at the same time guarantees that the information will be processed in the same order it was created and no information is lost.

I have implemented this in a standalone example, it is contained in the next [blog post](#example-for-combining-op-and-cpp-with-wait-and-notify

Select where to go ...

The Blog
My Technical Blogs
Blogs Of Friends