HƯỚNG DẪN Realtime Programming in JAVA

Joe

Thành viên VIP
21/1/13
3,024
1,336
113
Hi

Realtime or Real-Time. What is it? Let's look on the web. Wiki says:
Real-time or real time describes various operations in computing or other processes that must guarantee response times within a specified time (deadline), usually a relatively short time. A real-time process is generally one that happens in defined time steps of maximum duration and fast enough to affect the environment in which it occurs, such as inputs to a computing system.
Got it? Well, again: if you talk to someone and he replies after an hour then the conversation is NOT in real time. Human conversation bases on an (unconscious) agreement that the dialog is a conversation if the interchanged talks happen within several seconds and when a partner has to think the realtime answer could be "let me think..." (or so similar).

You are an IT developer and if you don't know how real-time works or what real-time is then your IT professional life is in real danger. Nevertheless, as a JAVA developer you deal already daily with real-time programming. Huh? Yes. All kinds of event-listening are actions in real-time. Example:
Java:
    JButton but = new JButton("Hit me and see");
    but.addActionListener(e -> {
      System.out.println("You just have hit me!");
    });
This piece of codes is genuinely a real-time action. When you press the display button the line "You just have hit me!" is printed immediately on the console. A probable delay is in the microsecond-realm. After Wiki this delay is simply negligible. Thus in real-time. Now you know how many times you have worked in real-time.

BUT: all kinds of "action-listening" are internal. Meaning the (re)action happens within the apps and that is easy to develop the in-real-time codes. Don't confuse the different APIs which are used in the apps as external codes. The APIs constitute together with your own codes the app. Thus all in-real-time events are internal, NOT a bit external. External events are events that occur outside the apps and are triggered by external objects which are physically independent from each other: event trigger and event consumer.

So, the question is: Do you know how to work with real-time events like a human conversation between two or more independent persons? The in-real-time events between two or more independent apps that exchange and process events.

NO? Then let me show you how to develop in JAVA the real-time APIs that allow independent apps to work with each other. All we need is a group of at least two components (or objects):
  • Real-Time Event (or RTEvent)
  • Real-Time Event Monitor (or RTEventMonitor)
RTEvent is the interface that has to be implemented in each independent app (just like any internal JAVA event interface). RTEvent provides a to-be-implemented method onEvent(String msg). It's the callback method which has one parameter String msg. The msg content is freely defined in RTEventMonitor.

RTEventMonitor is the API that provides the in-real-time sessions for the apps. Each real-time app must be a RTEvent implementation and owns some RTEventMonitors (at least one). With the provided methods external events can be registered (associated with) and published to external those who monitor. Each monitored RTEvent is tagged by a date-timestamp (dd/MM/yyyy hh:mm:ss) and can be logged in a file for an eventual later use. The format is as simple as possible:
Code:
            EventID: xyz date-timestamp Message-String
Example of a log:
Code:
EventID: DirectoryWatch
- Msg_0:  Sent: 16/02/2021 09:39:07, received: 16/02/2021 09:39:07. File: C:\JoeApp\realTime\film.txt is deleted
- Msg_1:  Sent: 16/02/2021 09:39:01, received: 16/02/2021 09:39:01. File: C:\JoeApp\realTime\film.txt is modified
- Msg_2:  Sent: 16/02/2021 09:39:01, received: 16/02/2021 09:39:01. File: C:\JoeApp\realTime\film.txt is modified
- Msg_3:  Sent: 16/02/2021 09:39:00, received: 16/02/2021 09:39:01. File: C:\JoeApp\realTime\film.txt is created
EventID: Download
- Msg_0:  Sent: 16/02/2021 09:38:22, received: 16/02/2021 09:38:22. https://i1.wp.com/asiatimes.com/wp-content/uploads/2021/02/US-China-US.jpg?resize=1200%2C749&ssl= to file:US-China-US.jpg is completed
RTEvent.java
Java:
void    onEvent(java.lang.String msg)
RTEventMonitor.java
Java:
Constructors:
RTEventMonitor( )
RTEventMonitor(String mcIP, int port)

Methods
void    associateEvent(Object event, String eventID)
void    clearLog(String fName)
void    clearMsgQueue(String eventID)
void    clearQueues()
void    close()
void    monitorEvent(Object event, String eventID)
void    monitorEvent(RTEvent event, String eventID)
void    publishEvent(String eventID, String msg)
void    removeEvent(String eventID)
void    setLog(.String fName, boolean ext)

String    getEventID(RTEvent event)

ArrayList<String>    getMsgQueue(String eventID)
Some coding examples:

Download.java
Java:
...
//
import joeapp.realtime.RTEventMonitor;
import joeapp.realtime.RTEvent;
// Joe Nartca(C)
public class Download extends JFrame implements Runnable, RTEvent {

  public Download(String IP, int port) throws Exception {
    monitor = new RTEventMonitor(IP, port);
    monitor.monitorEvent(this, "XDownload");
    //
    ...
    b0 = new JButton("Download");
    b0.addActionListener(e -> {
      this.url = InputPane.input(this, "URL for Download:");
      if (url != null && url.length() > 0) {
        b0.setEnabled(false);
        new Thread(this).start();
      }
    });
    JButton b1 = new JButton("EXIT");
    b1.addActionListener(e -> {
      if (monitor != null) {
        monitor.clearQueues();
        monitor.close();
      }
      System.exit(0);
    });
    ...
    setVisible(true);
  }
  public void run() {
    int b = url.lastIndexOf("/");
    if (b > 0) try {
      ...
      byte[] buf = new byte[65536];
      BufferedInputStream inp = new BufferedInputStream((new URL(url)).openStream());
      FileOutputStream fo = new FileOutputStream(fn, false);
      for(b = inp.read(buf); b > 0; b = inp.read(buf)) fo.write(buf, 0, b);
      inp.close();
      ...
      monitor.publishEvent("Download", "Download: "+url+" to file:"+fn+" is completed");
      ...
      return;
    } catch (Exception e) { }
    monitor.publishEvent("Download", "Download: "+url+". Unable to access this URL");
    b0.setEnabled(true);
  }
  // implemented RTEvent interface
  public void onEvent(String msg) {
    System.out.println("Download exits as requested.");
    System.exit(0);
  }
  public static void main(String... a) throws Exception {
    String IP = "224.0.0.3";
    int port = 8888;
    if (a.length == 2) {
      port = Integer.parseInt(a[1]);
      IP = a[0];
    }
    new Download(IP, port);
  }
  ...
  private RTEventMonitor monitor;
}
WatchDir.java
Java:
...
//
import joeapp.realtime.RTEventMonitor;
import joeapp.realtime.RTEvent;
// Joe Nartca (C)
public class WatchDir extends JFrame implements Runnable, RTEvent {

  public WatchDir(String IP, int port) throws Exception {
    monitor = new RTEventMonitor(IP, port);
    monitor.monitorEvent(this, "XDirectoryWatch");
    //
    ...
    JButton b0 = new JButton("Directory");
    b0.addActionListener(e -> {
      String dir = InputPane.input(this, "Directory to watch:");
      if (dir != null && dir.length() > 0) {
        b0.setEnabled(false);
        try { // C:\JoeApp\realTime
          ...
          new Thread(this).start();
        } catch (Exception ex) { }
      }
    });
    JButton b1 = new JButton("EXIT");
    b1.addActionListener(e -> {
      if (monitor != null) monitor.close();
      System.exit(0);
    });
    ...
  }
  // implemented RTEvent interface
  public void onEvent(String msg) {
    end = true;
    System.out.println("Directory Watcher exits as requested.");
    System.exit(0);
  }
  ...
  public void run() {
    WatchKey key;
    try {
      while(!end) {
        key = ws.take();
        Path P = keys.get(key);
        if (P != null) for (WatchEvent<?> event : key.pollEvents()) {
          WatchEvent.Kind kind = event.kind();
          if (kind == OVERFLOW) continue;
          Path path = (Path) event.context();
          Path child = P.resolve(path);
          String name = child.toString();
          if (kind == ENTRY_CREATE) {
            if (Files.isDirectory(child)) {
              registerAll(child);
              monitor.publishEvent("DirectoryWatch", "Directory: "+name+" is created");
            } else monitor.publishEvent("DirectoryWatch", "File: "+name+" is created");
          } else if (kind == ENTRY_MODIFY) {
              if (Files.isDirectory(child)) {
                monitor.publishEvent("DirectoryWatch", "Directory: "+name+" is modified");
            } else monitor.publishEvent("DirectoryWatch", "File: "+name+" is modified");
          } else if (kind == ENTRY_DELETE) {
              if (Files.isDirectory(child)) {
                monitor.publishEvent("DirectoryWatch", "Directory: "+name+" is deleted");
            } else monitor.publishEvent("DirectoryWatch", "File: "+name+" is deleted");
          }
          if (!key.reset()) {
            keys.remove(key);
            if (keys.isEmpty()) break;
          }
        }
      }
    } catch (Exception ex) {
      ex.printStackTrace();
      System.exit(0);
    }
  }
  public static void main(String[] a) throws Exception {
     if (a.length == 2) {
      new WatchDir(a[0], Integer.parseInt(a[1]));
    } else {
      new WatchDir("224.0.0.3", 8888);
    }
  }
  //
  ...
  private RTEventMonitor monitor;
  ...
}
RealTime.java: the RTEvent Monitoring App
Java:
...
//
import joeapp.realtime.RTEventMonitor;
import joeapp.realtime.RTEvent;
// Joe Nartca
// a Simple RTEventListener App
public class RealTimeApp extends JFrame implements RTEvent {
  public RealTimeApp(String IP, int port) throws Exception {
    this.port = port;
    this.IP = IP;
    setTitle("RealTime-Application");
    // NO list of previous session
    monitor = new RTEventMonitor(IP, port);
    monitor.monitorEvent(this, "Download");
    monitor.monitorEvent(this, "DirectoryWatch");
    monitor.clearLog("eventLog.txt");
    //
    ...
    JButton b0 = new JButton("Exit Download");
    b0.addActionListener(e -> {
      monitor.publishEvent("XDownload", "exit");
    });

    JButton b1 = new JButton("Exit Directory Watcher");
    b1.addActionListener(e -> {
      monitor.publishEvent("XDirectoryWatch", "exit");
    });
    JButton b2 = new JButton("EXIT");
    b2.addActionListener(e -> {
      if (monitor != null) monitor.close();
      System.exit(0);
    });
    ...
  }
  // implemented RTEvent interface
  public void onEvent(String msg) {
    jta.append("\nReceived RTEvent:\n"+msg+"\n");
    jta.setCaretPosition(jta.getDocument().getLength());
  }
  //
  public static void main(String... a) throws Exception {
    String IP = "224.0.0.3";
    int port = 8888;
    if (a.length == 2) {
      port = Integer.parseInt(a[1]);
      IP = a[0];
    }
    new RealTimeApp(IP, port);
  }
  ...
  private RTEventMonitor monitor;
}
The process with 3 independent apps (external RTEvents):
realtimeApp_1.png
The 2 buttons Exit Download and Exit Directory Watcher allow you from RealTimeApp to close the app Download or WatchDir using external RTEvent

The RTEventMonitor does work as internal RTEventMontitor, too.
realtimeApp.png
 
Sửa lần cuối:

Joe

Thành viên VIP
21/1/13
3,024
1,336
113
As mentioned in the first section External events are events that occur outside the apps and are triggered by external objects which are physically independent from each other: event trigger and event consumer. The across application boundary between RTEvent trigger and RTEvent consumer requires a medium that allows the events to propagate. The medium of human conversation is the air as the sound-propagating medium. Just like that Realtime events need a network to transport the events. The implementation of RTEventMonitor bases on UDP (User Datagram Protocol) and Multicast-IP (click HERE for more about the reserved Multicast IPv4 or IPv6).

The Realtime technology is old and simple: the RTEvent producer broadcasts its event with a determined event ID over the net using UDP and Multicast-IP while all RTEvent consumers listen the net for the swirling events and accept only the events that match the expected ID. All that occurs in realtime. Only the net latency causes some (negligible) delays. Meaning: every RTEvent consumer has the same chance at the same time to accept its event. No queueing in a loop.

The tricky matter is how to inform the RTEvent consumers over the net on certain RTEvent ID. To do that RTEvent is associated with an unique ID, then it has to be firstly propagated over the net for those who concern to register the event object with its associated ID. After that any RTEvent with an unique ID can be triggered and propagated on the net using the implemented method associateEvent() or monitorEvent(). Method associateEvent() or monitorEvent() must be issued before events with the method publishEvent() can be published.

RTEventMonitor has two constructors. The first one without parameter (or with defaults Multicast-IP 224.0.0.3, port 9876) and the second one is with two parameters: String Multicast-IP and int port. There are three ways of using RTEventMonitor:
  1. Application is an implementation of RTEvent: the event must be associated with an unique ID and then registered in RTEventMonitor using the method monitorEvent(RTEvent, eventID).
  2. Application is NOT an implementation of RTEvent: if the app just wants to consume RTEvent it must provide an implemented method onEvent(String msg) and registers itself with an unique event ID in RTEventMonitor using the method monitorEvent(Object, eventID).
  3. Application is just a RTEvent publisher and NOT an implementation of RTEvent: if the app just wants to publish RTEvent it needs only to associate itself with an unique event ID in RTEventMonitor using the method associateEvent(Object, eventID).
Note: as mentioned, RTEvent ID must be unique among themselves.

Examples:

RTEvent implementation as RTEvent consumer and publisher:
Java:
public class Download extends JFrame implements Runnable, RTEvent {
  public Download(String IP, int port) throws Exception {
    monitor = new RTEventMonitor(IP, port);
    monitor.monitorEvent(this, "XDownload"); // 'this' here is a RTEvent implementation
    //
    setTitle("Download");
    ...
  }
  ...
  public void onEvent(String msg) {
    ...
  }
  ...
}
As merely RTEvent consumer with callback onEvent():
Java:
public class Download extends JFrame implements Runnable {
  public Download(String IP, int port) throws Exception {
    monitor = new RTEventMonitor(IP, port);
    monitor.monitorEvent(this, "XDownload"); // 'this' here is an JFrame child object
    //
    setTitle("Download");
    ...
  }
  ...
  public void onEvent(String msg) {
    ...
  }
  ...
}
As merely RTEvent publisher without method onEvent():
Java:
public class Download extends JFrame implements Runnable {
  public Download(String IP, int port) throws Exception {
    monitor = new RTEventMonitor(IP, port);
    monitor.associateEvent(this, "XDownload"); // 'this' here is an JFrame child object
    //
    setTitle("Download");
    ...
  }
  ...
}
The rest of the RTEventMonitor methods are self-explained.

Joe


The zip file contains
  • examples/externalRTEvent directory contain 5 java sources and setCP.bat
  • examples/internalRTEvent directory contain 4 java sources and setCP.bat
  • RTEvent.java, RTEventMonitor.java, build.bat and realtime.jar

How to work with RTEvent package
  • Unzip the file to any directory of your wish
  • Open the setCP.bat in directory examples/externalRTEvent and examples/internalRTEvent and correct the line
    Code:
    c:\JoeApp\realtime\realtime.jar
    to your directory
  • Run it
  • Compile the sources as following (on a console)
    Code:
    javac -g:none -d ./classes *.java

That is, folk!

PS. Sorry for my forgetfullness. Here is the ZIP file RT.zip
 

Attachments

  • 17.9 KB Lượt xem: 0
Sửa lần cuối: