Andre's Blog

Andre's Technical Blog About Coding In Java/Groovy


20160626 About This Java Blog
20160626 Sending Objects Via Sockets
20160710 Adding Groovy To This Blog
20160710 Calling Groovy From Java To Read Json
20160717 Find Your Local IP Address
20161008 Reflection
20161028 Example For Combining OP And CPP With Wait And notify

20160626 About This Java Blog

To know why I write a blog about Java, please read my blog post

20160626 Sending Objects Via Sockets

For my software project I have to implement a communication between different PCs.

I have decided :

  1. I want to communicate via sockets.
  2. I want to communicate using objects.

For more information about why I decided to do this with objects via sockets please read my blog post.

Here I show you some code-snippets of how I did it.

I did not focus on closing the sockets and so on, the code is really only meant as example for showing how to implement the object via socket communication.

This is the complete example code including my build.gradle script : zipped example of Sending Objects Via Sockets

How to build and run the example :

gradle jar
java -jar build/libs/CISystem.jar

The main function :

public static void main(String... args) throws IOException {
  System.out.println("Setting up threads...");
  Thread serverThread = new Thread(new CIServerSocket());
  serverThread.start();
  Thread clientThread = new Thread(new CIClientSocket());
  clientThread.start();
}

The class of the object to send :

public class TestData implements Serializable {

  public String message;
  public int number;
  public File fileHandle;
}

The client code :

public class CIClientSocket implements Runnable {

  Socket socket = null;
  ObjectInputStream inputStream = null;
  ObjectOutputStream outputStream = null;

  public void test() {

    System.out.println("client receives data");
    try {
      while (true) {

        TestData testData = (TestData)inputStream.readObject();

        System.out.println("client has received this data :");
        System.out.println(testData.message);
        System.out.println(testData.number);
        System.out.println(testData.fileHandle.getPath());
      }
    } catch (Exception e) {
      System.out.println(e);
    }

    System.out.println("client stopped");
  }

  public void run() {
    try {
      connect();
      test();
    } catch (Exception e) {
      System.out.println(e);
    }
  }

  public void connect() throws Exception {
    System.out.println("Client connecting ......");
    socket = new Socket("localhost", 4444);
    inputStream = new ObjectInputStream(socket.getInputStream());
    outputStream = new ObjectOutputStream(socket.getOutputStream());
    System.out.println("Client connected ......");
  }

}

The server code :

public class CIServerSocket implements Runnable {

  ServerSocket server;
  ObjectOutputStream outputStream;
  //Solution 2: when only changing an existing memeber object before sending ...
  TestData testData = new TestData();

  public void send(String message, int number, File fileHandle) {
    try {

      System.out.println("server sends data : ");
      System.out.println(message);
      System.out.println(number);
      System.out.println(fileHandle.getPath());

      //solution 1: create a new object to send everytime ...
      //TestData testData = new TestData();
      testData.message = message;
      testData.number = number;
      testData.fileHandle = fileHandle;

      //solution 1 : ... so java will serialize the object always
      //             and cannot use an old reference
      //outputStream.writeObject(testData);

      //solution 2: ... tell java to treat object to send as new object
      //                and not to use hashed version due to old reference
      outputStream.writeUnshared(testData);
      outputStream.flush();
      System.out.println("server flushed");

    } catch (Exception e) {
      System.out.println(e);
    }
  }

  public void test() {

    try {
      Socket socket = server.accept();

      System.out.println("server accepted connection");
      outputStream = new ObjectOutputStream(socket.getOutputStream());

      System.out.println("server has created the outputstream");

      System.out.println("server sends data");

      send("hello world", 1, new File("/home/user/blog"));
      send("how are you", 22, new File("c:\\home\\user\\blog"));
      send("yeah!!!", 333, new File("/usr/local/bin"));
    } catch (Exception e) {
      System.out.println(e);
    }

  }

  public void run() {
    server = connect();
    test();
  }

  public ServerSocket connect() {
    ServerSocket ss=null;
    System.out.println("Server listening");
    try{
      ss = new ServerSocket(4444);
    } catch(IOException e) {
      e.printStackTrace();
      System.out.println("Server error");
    }

    return ss;
  }

}

The console output :

Setting up threads...
Server listening
Client connecting ......
server accepted connection
server has created the outputstream
server sends data
server sends data :
hello world
1
/home/user/blog
Client connected ......
client receives data
server flushed
server sends data :
how are you
22
c:\home\user\blog
server flushed
server sends data :
yeah!!!
333
/usr/local/bin
server flushed
client has received this data :
hello world
1
/home/user/blog
client has received this data :
how are you
22
c:\home\user\blog
client has received this data :
yeah!!!
333
/usr/local/bin

20160710 Adding Groovy To This Blog

Since I start using Groovy code in my Java programs I share examples of the Groovy code here, too.

20160710 Calling Groovy From Java To Read Json

For my software project CISystem I have to read a configuration containing some information about a server and a list of client addresses.

I have decided to read the configuration from a Json file and since Java has no native Json support and I did not want to use third party jars I haver decided to call a Groovy script instead, because Groovy has native Json support and CISystem will have other connections to using Groovy.

For more information about how I came to write this code please read my blog post.

Here I show you the code.

I did not focus on implementing a proper exception handling, the code is really only meant as example for showing how to call Groovy scripts from Java and how to read a Json file in Groovy.

This is the complete example code : zipped example of Calling Groovy From Java To Read Json

I have skipped providing a gradle file, you would have to adapt the classpath to the groovy jar and maybe it is interesting for some of you how to do it directly in the shell.

How to build and run the example, please adapt the classpath :

javac CIConfigNetwork.java
javac -cp .:/home/amos/bin/groovy-2.4.6/embeddable/groovy-all-2.4.6.jar ReadConfigNetworkExample.java
java -cp .:/home/amos/bin/groovy-2.4.6/embeddable/groovy-all-2.4.6.jar ReadConfigNetworkExample

A helper class to handle pairs, you could also use it for key-value pairs, but I wanted to have more abstract names for the member variables, because an IP address is no key for the port value when you have several ports in use for the same IP :

public class CIPair<L,R> {

  public L leftValue;
  public R rightValue;

}

The Java class representing the Json configuration :

import java.util.ArrayList;

public class CIConfigNetwork {

  public String myName;
  public String myPort;
  public ArrayList<CIPair> nodeList = new ArrayList<CIPair>();

}

The Groovy script :

import groovy.json.JsonSlurper
import CIConfigNetwork

CIConfigNetwork runScript(CIConfigNetwork input) {
  String inputString = new File("configNetwork.json").text

  JsonSlurper jsonSlurper = new JsonSlurper()

  Map jsonResult = (Map)jsonSlurper.parseText(inputString)

  input.myName = jsonResult['myName']
  input.myPort = jsonResult['myPort']

  List nodes = (List)jsonResult['nodeList']

  for (node in nodes) {
    Map m = (Map)node
    CIPair<String, String> pair = new CIPair<String, String>()
    pair.leftValue = m.get("IP")
    pair.rightValue = m.get("Port")
    input.nodeList.add(pair)
  }

  return input
}

def printConfigNetwork(CIConfigNetwork cicn) {
  println "Server " + cicn.myName + ":" + cicn.myPort
  for (node in cicn.nodeList) {
    println "Node   " + node.leftValue + ":" + node.rightValue
  }
}

CIConfigNetwork cicn = new CIConfigNetwork()
CIConfigNetwork cicnOut = runScript(cicn)
println "Within groovy script : the reference passed as parameter"
printConfigNetwork(cicn)

println "Within groovy script : the reference returned by the function"
printConfigNetwork(cicnOut)

You can execute it standalone for testing with :

groovy ReadConfigNetworkJson.groovy

and it should produce this output :

Within groovy script : the reference passed as parameter
Server N150:8900
Node   localhost:8910
Node   localhost:8911
Within groovy script : the reference returned by the function
Server N150:8900
Node   localhost:8910
Node   localhost:8911

This is the Java code calling the Groovy script :

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import java.io.File;

public class ReadConfigNetworkExample {

  public static CIConfigNetwork readConfigNetwork(CIConfigNetwork cicn) throws Exception {

    final GroovyClassLoader classLoader = new GroovyClassLoader();

    Class groovy = classLoader.parseClass(new File("ReadConfigNetworkJson.groovy"));
    GroovyObject groovyObj = (GroovyObject)groovy.newInstance();

    CIConfigNetwork rv = (CIConfigNetwork)groovyObj.invokeMethod("runScript", new Object[] {cicn});

    System.out.println("Within Java : the input parameter");
    groovyObj.invokeMethod("printConfigNetwork", new Object[] {cicn});

    System.out.println("Within Java : the return value");
    groovyObj.invokeMethod("printConfigNetwork", new Object[] {rv});

    return rv;
  }

  public static void main(final String[] args) throws Exception {

    CIConfigNetwork cicn = new CIConfigNetwork();
    CIConfigNetwork rv = readConfigNetwork(cicn);
    System.out.println("Returned by Groovy : " + rv.myName + ":" + rv.myPort);
  }
}

You have to compile it including the classpath to the groovy-all-x.y.z.jar

javac -cp .:/home/amos/bin/groovy-2.4.6/embeddable/groovy-all-2.4.6.jar ReadConfigNetworkExample.java

and when calling it with something like (please adapt the path) this

java -cp .:/home/amos/bin/groovy-2.4.6/embeddable/groovy-all-2.4.6.jar ReadConfigNetworkExample

you should get this output :

Within Java : the input parameter
Server N150:8900
Node   localhost:8910
Node   localhost:8911
Within Java : the return value
Server N150:8900
Node   localhost:8910
Node   localhost:8911
Returned by Groovy : N150:8900

20160717 Find Your Local IP Address

The class CIConfigNetwork has members for the name and the port of the local node, but I did not provide a member for the local IP address.

The reason is, I did not want to configure this IP address every time in the Json configuration, because this address may change every time you connect to your router due to DHCP.

What I know is, every node in my network has an IP address like 10.0.0.x.

I will add another member like

String networkMask;

to CIConfigNetwork and then I can find the local IP address of a node with the Java classes NetworkInterface, InetAddress and Enumeration.

This is the complete example code including Gradle build script : zipped example of Find Your Local IP Address

To build and run the example :

gradle jar
java -jar build/libs/FindIPAddress.jar

This is an example of how the code would work, put it into a function, return the address string instead of printing it and you have your local IP address :

package com.wartbar.cisystem;

import java.io.IOException;
import java.net.NetworkInterface;
import java.net.InetAddress;
import java.util.Enumeration;

public class FindIPAddress {

  public static void checkNet(String addressPattern) throws Exception
  {
    Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
    while (interfaces.hasMoreElements())
    {
      NetworkInterface ni = interfaces.nextElement();

      Enumeration<InetAddress> addresses = ni.getInetAddresses();
      while (addresses.hasMoreElements())
      {
        InetAddress address = addresses.nextElement();
        String addressString = address.getHostAddress();
        if (addressString.contains(addressPattern)) {
          System.out.println("Your address is : " + addressString);
        }
      }
    }
  }

  public static void main(String... args) throws IOException {

    try {
      checkNet("10.0.0.");
    } catch(Exception e) {
      System.out.println(e.getMessage());
    }
  }
}

For more information about how I came to write this code please read my blog post.

20160820 Example For Multi Threading And Synchronized Data Structure Access

As mentioned in this blog post I have implemented a spike/test which shall show, that I am able to implement the Requirements For CISystem regarding multi threading and synchronized data structures holding the information about the nodes of the network.

My idea is to abstract from real node information (IP address, port number, name, ...) and to use just a map instead, where the key (of the node) is just a character of the alphabet and the value is an Integer value, which is increased by 1 every time a thread adds its information to the map.

This is the description of what the classes/threads of my example do :

  1. The class Threading owns the Map and creates the other threads
  2. The Worker threads write an array of information (character strings) 10.000 times into the Map
  3. The Reader thread reads 5 times the complete Map while it is filled by the Worker threads
  4. The class Threading waits for all other threads to end to present the final state/content of the Map

This is the code of Threading.java

package com.wartbar.example;

import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;

public class Threading {

  public static Map<String, Integer> synchronizedMap = null;
  public static List<Thread> threads = new ArrayList<Thread>();

  public static void initSynchronizedMap() {
    Map<String, Integer> unsynchronizedMap = new HashMap<String, Integer>();
    synchronizedMap = Collections.synchronizedMap(unsynchronizedMap);
  }

  public static void add(String item) {
    synchronized(synchronizedMap) {
      Integer value = 1;
      if (synchronizedMap.containsKey(item)) {
        value = synchronizedMap.get(item);
        value++;
      }
      synchronizedMap.put(item,value);
    }
  }

  public Threading() {
    initSynchronizedMap();

    String[] info = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n"};

    for (int i=0; i<50; i++) {
      Thread t = new Thread(new Worker(info));
      t.start();
      threads.add(t);
    }

    Thread reader = new Thread(new Reader());
    reader.start();
    threads.add(reader);

    try {
      for (Thread t : threads) {
        t.join();
      }
    } catch (Exception e) {
      System.out.println(e);
    }

    synchronized(synchronizedMap) {
      System.out.println("Final state of the map: ");
      for (String item : synchronizedMap.keySet()) {
        System.out.println(item + ":" + synchronizedMap.get(item));
      }
    }
  }

}

This is the code of Worker.java

package com.wartbar.example;

public class Worker implements Runnable {

  private String myInfo[];

  public Worker(String[] info) {
    myInfo = info;
  }

  public void run() {
    try {
      for (int i=0; i<10000; i++) {
        for (String item : myInfo) {
          Threading.add(item);
        }
      }
    } catch (Exception e) {
      System.out.println(e);
    }
  }
}

This is the code of Reader.java

package com.wartbar.example;

public class Reader implements Runnable {

  public void run() {
    try {
      for (int i=0; i<5; i++) {
        synchronized(Threading.synchronizedMap) {
            System.out.println("Intermediate state of the map :");
            for (String item : Threading.synchronizedMap.keySet()) {
              System.out.println(item + ":" + Threading.synchronizedMap.get(item));
            }
        }
        Thread.sleep(1000);
      }
    } catch (Exception e) {
      System.out.println(e);
    }
  }
}

and this is the output when creating an object with new Threading()

Intermediate state of the map :
a:4338
b:4333
c:4330
d:4324
e:4323
f:4320
g:4316
h:4314
i:4313
j:4311
k:4308
l:4306
m:4306
n:4303
Intermediate state of the map :
a:112741
b:112736
c:112731
d:112726
e:112723
f:112720
g:112719
h:112715
i:112710
j:112707
k:112705
l:112703
m:112698
n:112696
Intermediate state of the map :
a:202609
b:202606
c:202599
d:202594
e:202591
f:202589
g:202587
h:202581
i:202579
j:202576
k:202573
l:202570
m:202569
n:202566
Intermediate state of the map :
a:292532
b:292525
c:292519
d:292508
e:292504
f:292503
g:292503
h:292502
i:292500
j:292499
k:292499
l:292498
m:292494
n:292491
Intermediate state of the map :
a:379525
b:379519
c:379518
d:379516
e:379513
f:379508
g:379506
h:379505
i:379504
j:379503
k:379500
l:379500
m:379499
n:379495
Final state of the map:
a:500000
b:500000
c:500000
d:500000
e:500000
f:500000
g:500000
h:500000
i:500000
j:500000
k:500000
l:500000
m:500000
n:500000

20161008 Reflection

This is a small explanation for how to use reflection in Java like I do in my example for code of CISystem.

This explanation shall not replace a documentation, it is by no means complete and I am no expert for this yet, but since I did not had much more when I started, I thought this might be interesting for you :

You ask with Class.forName() for the class object.

You have to pass the full qualified class name, including the full package structure.

This example shows it for a String :

Class<?> classType = Class.forName("java.lang.String");

With classType.getConstructor() you get the default constructor :

    Constructor<?> ctor = classType.getConstructor();

With the constructor and a type cast you create your object :

String s = (String)ctor.newInstance();

When you want to request a constructor which requires parameters, you provide a variable argument list when requesting the constructor with getConstructor(Class<?>... parameterTypes) and you pass a variable argument list containing these parameters calling newInstance(Object... initargs).

This example shows how to do it with creating a String :

        Class<?> clazz = Class.forName("java.lang.String");
        Constructor<?> ctor = clazz.getConstructor(String.class);
        String s = (String)ctor.newInstance(new Object[] { "Hello World!" });
        System.out.println(s);

which prints

  Hello World!

20161028 Example For Combining OP And CPP With Wait And Notify

This is the example implementation for how I want to implement the Communication In CISystem Between Threads.

The server thread produces String messages, which are passed to the clients by using the Observer Pattern implementation, the class Observable provided by Java.

The clients implement the Observer interface to be able to pass new information to them and they get a wake up call for this so they don't need to wait actively for the server to produce something.

This is the main class :

package com.wartbar.main;

import com.wartbar.client.OClient;
import com.wartbar.server.OServer;

/**
 * Created by amos on 28.10.16.
 */
public class Main {

    public static void main(String... args) {
        System.out.println("Starting threaded Observer-Pattern Example");

        OServer server = new OServer();

        for (int i=1; i<=5; i++) {
            String name = "C" + i;
            OClient client = new OClient(name, server);
            server.addObserver(client);
            Thread t = new Thread(client);
            t.start();
        }

        Thread t = new Thread(server);
        t.start();
    }
}

This is the server class :

package com.wartbar.server;

import java.util.ArrayList;
import java.util.Observable;

/**
 * Created by amos on 28.10.16.
 */
public class OServer extends Observable implements Runnable {

    private ArrayList<String> list = new ArrayList<>();
    private int counter = 0;

    private void produceMessage() {
        counter++;
        String message = "Message " + counter;
        list.add(message);
        System.out.println("server notifies " + countObservers() + " observers for " + message);
    }

    private void distributeMessage() {
        setChanged();
        notifyObservers(list);
    }

    private void wakeUpClients() {
        notifyAll();
    }

    private void prepareList() {
        list.clear();
        System.out.println("server has cleared the list, only new messages will be communicated!");
    }

    /*
     * prepare the list (clear it),
     * produce a message,
     * distribute the message via Observer pattern,
     * wake up the client threads
     */
    synchronized public void communicateMessage() {
        prepareList();
        produceMessage();
        distributeMessage();
        wakeUpClients();
    }

    private void sleepOneMilliSecond() {
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * communicates 25x with clients,
     * sleep(1) only necessary in this example to give clients a chance to consume before producer has finished
     */
    private void communicationLoop() {
        for (int i=0; i<5; i++) {
            for (int j=0; j<5; j++) {
                communicateMessage();
            }
            sleepOneMilliSecond();
        }
        System.out.println("server has stopped production");
    }

    private void lastWakeUpClients() {
        synchronized (this) {
            System.out.println("last notification of the client threads");
            notifyAll();
        }
    }

    @Override
    public void run() {
        try {
            communicationLoop();

            /*
             * It is not guaranteed the clients have consumed everything before the server stopped the production!
             * In this case the server informed via console that it stopped production,
             * but there are clients which still have to consume.
             * To do this we need to wake them up a last time!
             */
            lastWakeUpClients();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

and this is the client class :

package com.wartbar.client;

import com.wartbar.server.OServer;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

/**
 * Created by amos on 28.10.16.
 */
public class OClient implements Runnable, Observer {

    ArrayList<String> messages = new ArrayList<>();
    String id;
    OServer server;

    public OClient(String name, OServer server) {
        this.id = name;
        this.server = server;
    }

    private void waitForServer() {
        System.out.println("client " + id + " starts to wait for the server");
        try {
            server.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void consumeMessages() {
        messages.clear();
    }

    private void reportMessages() {
        System.out.println("client " + id + " : " + messages.size() + " messages in list");
        for (String s : messages) {
            System.out.println("client " + id + " : " + s);
        }
    }

    /*
     * wait for the wake-up from the server,
     * report the messages, which were distributed by the server via the Observer-Pattern,
     * consume the messages (clear the list)
     */
    private void communicate() {
        /*
         * synchronizing via server
         *
         * 1. enables us to wait for the server signal that something is produced (no active-wait-polling!)
         * 2. guarantees the code block will be executed without interruption
         *
         */
        synchronized(server) {
            waitForServer();
            reportMessages();
            consumeMessages();
        }
    }

    @Override
    public void run() {
        try {
            while (true) {
                communicate();
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    @Override
    public void update(Observable o, Object arg) {
        /*
         * take the messages from ther server
         */
        ArrayList<String> serverMessages = (ArrayList<String>)(arg);

        /*
         * copy the messages to this clients list
         */
        messages.addAll(serverMessages);

        System.out.println("client " + id + " is updated");
    }
}

and this is the output :

amos$ java -jar build/libs/ObserverProject-all.jar
Starting threaded Observer-Pattern Example
client C1 starts to wait for the server
client C3 starts to wait for the server
client C2 starts to wait for the server
client C4 starts to wait for the server
client C5 starts to wait for the server
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 1
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 2
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 3
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 4
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 5
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
client C5 : 5 messages in list
client C5 : Message 1
client C5 : Message 2
client C5 : Message 3
client C5 : Message 4
client C5 : Message 5
client C5 starts to wait for the server
client C4 : 5 messages in list
client C4 : Message 1
client C4 : Message 2
client C4 : Message 3
client C4 : Message 4
client C4 : Message 5
client C4 starts to wait for the server
client C2 : 5 messages in list
client C2 : Message 1
client C2 : Message 2
client C2 : Message 3
client C2 : Message 4
client C2 : Message 5
client C2 starts to wait for the server
client C3 : 5 messages in list
client C3 : Message 1
client C3 : Message 2
client C3 : Message 3
client C3 : Message 4
client C3 : Message 5
client C3 starts to wait for the server
client C1 : 5 messages in list
client C1 : Message 1
client C1 : Message 2
client C1 : Message 3
client C1 : Message 4
client C1 : Message 5
client C1 starts to wait for the server
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 6
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 7
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 8
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 9
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 10
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
client C1 : 5 messages in list
client C1 : Message 6
client C1 : Message 7
client C1 : Message 8
client C1 : Message 9
client C1 : Message 10
client C1 starts to wait for the server
client C3 : 5 messages in list
client C3 : Message 6
client C3 : Message 7
client C3 : Message 8
client C3 : Message 9
client C3 : Message 10
client C3 starts to wait for the server
client C2 : 5 messages in list
client C2 : Message 6
client C2 : Message 7
client C2 : Message 8
client C2 : Message 9
client C2 : Message 10
client C2 starts to wait for the server
client C4 : 5 messages in list
client C4 : Message 6
client C4 : Message 7
client C4 : Message 8
client C4 : Message 9
client C4 : Message 10
client C4 starts to wait for the server
client C5 : 5 messages in list
client C5 : Message 6
client C5 : Message 7
client C5 : Message 8
client C5 : Message 9
client C5 : Message 10
client C5 starts to wait for the server
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 11
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 12
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 13
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 14
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 15
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
client C5 : 5 messages in list
client C5 : Message 11
client C5 : Message 12
client C5 : Message 13
client C5 : Message 14
client C5 : Message 15
client C5 starts to wait for the server
client C4 : 5 messages in list
client C4 : Message 11
client C4 : Message 12
client C4 : Message 13
client C4 : Message 14
client C4 : Message 15
client C4 starts to wait for the server
client C2 : 5 messages in list
client C2 : Message 11
client C2 : Message 12
client C2 : Message 13
client C2 : Message 14
client C2 : Message 15
client C2 starts to wait for the server
client C3 : 5 messages in list
client C3 : Message 11
client C3 : Message 12
client C3 : Message 13
client C3 : Message 14
client C3 : Message 15
client C3 starts to wait for the server
client C1 : 5 messages in list
client C1 : Message 11
client C1 : Message 12
client C1 : Message 13
client C1 : Message 14
client C1 : Message 15
client C1 starts to wait for the server
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 16
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 17
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 18
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 19
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 20
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
client C1 : 5 messages in list
client C1 : Message 16
client C1 : Message 17
client C1 : Message 18
client C1 : Message 19
client C1 : Message 20
client C1 starts to wait for the server
client C3 : 5 messages in list
client C3 : Message 16
client C3 : Message 17
client C3 : Message 18
client C3 : Message 19
client C3 : Message 20
client C3 starts to wait for the server
client C2 : 5 messages in list
client C2 : Message 16
client C2 : Message 17
client C2 : Message 18
client C2 : Message 19
client C2 : Message 20
client C2 starts to wait for the server
client C4 : 5 messages in list
client C4 : Message 16
client C4 : Message 17
client C4 : Message 18
client C4 : Message 19
client C4 : Message 20
client C4 starts to wait for the server
client C5 : 5 messages in list
client C5 : Message 16
client C5 : Message 17
client C5 : Message 18
client C5 : Message 19
client C5 : Message 20
client C5 starts to wait for the server
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 21
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 22
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 23
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 24
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
server has cleared the list, only new messages will be communicated!
server notifies 5 observers for Message 25
client C5 is updated
client C4 is updated
client C3 is updated
client C2 is updated
client C1 is updated
client C5 : 5 messages in list
client C5 : Message 21
client C5 : Message 22
client C5 : Message 23
client C5 : Message 24
client C5 : Message 25
client C5 starts to wait for the server
client C4 : 5 messages in list
client C4 : Message 21
client C4 : Message 22
client C4 : Message 23
client C4 : Message 24
client C4 : Message 25
client C4 starts to wait for the server
client C2 : 5 messages in list
client C2 : Message 21
client C2 : Message 22
client C2 : Message 23
client C2 : Message 24
client C2 : Message 25
client C2 starts to wait for the server
client C3 : 5 messages in list
client C3 : Message 21
client C3 : Message 22
client C3 : Message 23
client C3 : Message 24
client C3 : Message 25
client C3 starts to wait for the server
client C1 : 5 messages in list
client C1 : Message 21
client C1 : Message 22
client C1 : Message 23
client C1 : Message 24
client C1 : Message 25
client C1 starts to wait for the server
server has stopped production
last notification of the client threads
client C1 : 0 messages in list
client C1 starts to wait for the server
client C3 : 0 messages in list
client C3 starts to wait for the server
client C2 : 0 messages in list
client C2 starts to wait for the server
client C4 : 0 messages in list
client C4 starts to wait for the server
client C5 : 0 messages in list
client C5 starts to wait for the server

Select where to go ...


The Blog
My Technical Blogs
Projects
Blogs Of Friends
RSS
CV/About
Me