A Technology Blog About Code Development, Architecture, Operating System, Hardware, Tips and Tutorials for Developers.

Monday, August 30, 2010

INCOMPLETE ROAD MAP TO Thread.run()

8:40:00 PM Posted by Satish Kumar , , 1 comment

When it comes to java thread, I always try to dig how the Thread.run() method get executed when, the Thread.start() method get called. Recently, I downloaded the JDK 5 source code and started looking into the implementation.

There is two way we can create user defined threads and in both the scenarios, we used to call the Thread constructor and that internally calls the Thread.init(). init() has the following signature. Basically this method initialize the Thread class members like group, daemon, priority, name etc.

private void init(ThreadGroup paramThreadGroup, Runnable paramRunnable, String paramString, long paramLong);

Now the actual game begins, when you call the start() on a thread object. start() method adds the thread to a thread group as per the initializing parameter. And here the start() calls a native method start0() after that. To find out further, I started looking at the Thread's native implementation.Starting with \JDK 1.5 Source\j2se\src\share\native\java\lang\Thread.c, I found the start0() method is mapped to (void *)&JVM_StartThread (refer line no 25). In \JDK 1.5 Source\j2se\src\share\javavm\export\jvm.h from line no 206 to 256 JNI configuration is there for Thread class native implementation.

Now it is time to jump to the implementation of (void *)&JVM_StartThread method. \JDK 1.5 Source\hotspot\src\share\vm\prims\jvm.cpp contains the implementation of above method. This method basically create a native Java thread and starts the same (refer from line no. 2257 to 2314).

To see the native thread start method, I went to \JDK 1.5 Source\hotspot\src\share\vm\runtime\thread.cpp. In the Thread::start(Thread* thread) method, the particular thread is initialized to RUNNABLE state followed by passing the thread reference to os.

In \JDK 1.5 Source\hotspot\src\share\vm\runtime\os.cpp, the os::start_thread(Thread* thread) method creates a OS thread.

As I have limited exposure in C/C++, I could not move further. But I discussed this in some of the Java forums and found that there will be different thread implementation for different OS and once the OS thread is created, the OS calls and manages the Thread.run() method according to it's own mechanism.

To move further in this, I was needing a C/C++ developer and could probably have looked in to the OS level. I started looking in to Ubuntu, but got confused. So finally left that there.  

Tuesday, August 10, 2010

JAVA EVENT DELEGATION MODEL

10:09:00 PM Posted by Satish Kumar , , , , 4 comments
Event broadcasting sytem in java  called as EVENT DELEGATION MODEL. This model is based on the Event Source and Event Listeners. Event Listener is an object that receives the message/ events. The Event Source is any object which creates the message/ event. The Event Delegation Model is based on the following things.
  • Event Source - This class which broadcasts the events.
  • Event Listeners - The classes which receive notifications of events. The Event Listeners are implemented to Adapter classes for the default action for a particular event. The API user is free to override the Adapter version of the method. The event listeners should extend the java.util.EventListener interface.
  • Event Object - The object which describes the event. The event object class should extend java.util.EventObject class.
  • Event Manager - This is the class which manages the relationship between the event and listeners. This class will register and de-register the listeners for a particular event.
The following picture explains how the event model works.


Now time to look at the programming implementation.

Event Class:

1
2
3
4
5
6
7
8
import java.util.EventObject;

//Declare the event. It must extend EventObject.
public class MyEvent extends EventObject {
    public MyEvent(Object source) {
        super(source);
    }
}

Event Listener:

1
2
3
4
5
6
7
8
9
package org.satish.event;

import java.util.EventListener;

//Declare the listener class. It must extend EventListener.
//A class must implement this interface to get MyEvents.
public interface MyEventListener extends EventListener {
    public void myEventOccurred(MyEvent evt);
}

Event Manager:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package org.satish.event;

import java.util.ArrayList;
import java.util.List;

//Add the event registration and notification code to a class. 
public class EventManager {
    // Create the listener list
    protected List listenerList = new ArrayList();

    // This methods allows classes to register for MyEvents
    public void addMyEventListener(MyEventListener listener) {
        listenerList.add(listener);
    }

    // This methods allows classes to unregister for MyEvents
    public void removeMyEventListener(MyEventListener listener) {
        listenerList.remove(listener);
    }

    // This method is used to fire MyEvents
    void fireMyEvent(MyEvent evt) {
        System.out.println("Got the event." + listenerList.size());
        // Iterate the Listener list to fire the implemented method of each
        // listener.
        for (MyEventListener myEventListener : listenerList) {
            System.out
                    .println("Firing listener method for each of the listener.");
            myEventListener.myEventOccurred(evt);
        }
    }
}

Event Source:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package org.satish.event;

public class EventGenerator implements Runnable{
    
    Thread t;
    EventManager c;
    public EventGenerator(EventManager c) {
        // TODO Auto-generated constructor stub
        this.c = c;
        t =  new Thread(this, "Event Generator");
        t.start();
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("Event generator in the run method.");
        while(true){
            System.out.println("Generate a event.");
            c.fireMyEvent(new MyEvent(this));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO: handle exception
            }
        }
    }
}

Demo Starter:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package org.satish.event;

public class EventDemo {
    public static void main(String[] args) {

        EventManager c = new EventManager();

        // Event Generator is instantiated to generate the events.
        EventGenerator eventGenerator = new EventGenerator(c);
        System.out.println("Event generator started.");

        // Register for MyEvents from c
        // Here the object of MyEventListener is been created, implementing the
        // interface method. Developers are free to user the Adapter class
        // object or use their own implementation class object.
        c.addMyEventListener(new MyEventListener() {
            public void myEventOccurred(MyEvent evt) {
                // MyEvent was fired
                System.out.println("1st Event Fired");
            }
        });
        System.out.println("First event is registered.");

        // Register another event
        c.addMyEventListener(new MyEventListener() {
            public void myEventOccurred(MyEvent evt) {
                // MyEvent was fired
                System.out.println(" 2nd Event Fired");
            }
        });
        System.out.println("Second event is registered.");
    }
}


This is the basic implementation of event delegation model. In a multi threaded environment, where more than one listener are registered to each event and the generation of event is quite fast, then you need to change your design to deal with the requirement.

Source Code:

Complete source code you can fork from GitHub.