Andre's Blog

20160820 A Spike For Implementing The Threading Of CISystem



The next step in the implementation of CISystem will be the data structure storing the information about all known nodes and how to fill it.

My idea is that there will be a thread running a server socket and this thread starts a new thread for every incoming client connection. These client threads will be informed about how the network of nodes looks like and store this information in a map. This means several threads write into the map at the same time.

Another thread will check the map for new nodes to where a new connection has to be created. This thread constantly reads the map and creates new threads which open client connections to the server sockets of the other nodes. This shall happen only once per second or less often.

Finally I expect I have to react to the end of threads, for example when a socket connection is closed because a node goes offline, a scenario which is mentioned in the Requirement Specification Of CISystem.

Together this means I have to implement a lot of classes writing and reading a map at the same time. It will be a multi threaded application where nearly all threads access the same data structure.

FYI: Except for the simple unsynchronized threads in my example for Sending Objects Via Sockets I did not implement a multi threaded application before.

To prepare myself for this task I did the following :

  1. I have searched Google for hints and examples
  2. I have found out that java.util.collections provides synchronized maps
  3. I have learned at java2s how Thread.join() works
  4. I have asked a colleague about the connection between the synchronized statement and a synchronized map

After speaking to my colleague I have a better understanding of the java documentation of synchronizedMap :

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)

Returns a synchronized (thread-safe) map backed by the specified map.
In order to guarantee serial access, it is critical that all access
to the backing map is accomplished through the returned map.

It is imperative that the user manually synchronize on the returned map
when iterating over any of its collection views:

  Map m = Collections.synchronizedMap(new HashMap());
  Set s = m.keySet();  // Needn't be in synchronized block
  synchronized (m) {  // Synchronizing on m, not s!
      Iterator i = s.iterator(); // Must be in synchronized block
      while (i.hasNext())

Failure to follow this advice may result in non-deterministic behavior.

It means calling every function of the synchronized map is thread safe, but when you need to iterate over the complete map without being interrupted, you need to do this in a synchronized block. You could use any other object for this synchronization, but it makes sense to synchronize the access to a data structure with using the reference to this data structure.

Summarized I have learned to :

  1. create a synchronized map with Collections.synchronizedMap(...)
  2. synchronize code blocks using the same monitor variable (can be any) using the synchronized(monitor variable reference) statement
  3. let one thread wait for other threads to terminate is done by calling Thread.join() at the other threads
  4. let a thread sleep for at least a second is done with Thread.sleep(1000) and should not be done in a synchronized code block!

Now that I have learned a lot about multi threading and the corresponding functionality, I have decided to start with a spike.

A spike is a test and its intention is to show that

  1. I have understood the problem
  2. I have understood all tools and how to use them
  3. I am able to solve a reasonable complex part problem with my tools

When my spike works I should be able to solve the real tasks for CISystem the same way.

Please find my description of the spike and its sourcecode in my Java blog :

Example For Multi Threaded Data Structure Access

Select where to go ...

The Blog
My Technical Blogs
Blogs Of Friends