Posted by Unknown on 9:51 AM
Labels:

Class loaders are hierarchical. Classes are introduced into the JVM as they are referenced by name in a class that is already running in the JVM. So how is the very first class loaded? The very first class is specially loaded with the help of static main() method declared in your class. All the subsequently loaded classes are loaded by the classes, which are already loaded and running. A class loader creates a namespace. All JVMs include at least one class loader that is embedded within the JVM called the primordial (or bootstrap) class loader. Now let’s look at non-primordial class loaders. The JVM has hooks in it to allow user defined class loaders to be used in place of primordial class loader. Let us look at the class loaders created by the JVM.

Bootstrap : JDK internal classes, java.* packages.
Extensions : jar files from JDK extensions directory
System : classes from system classpath.


Classes loaded by Bootstrap class loader have no visibility into classes loaded by its descendants (i.e Extensions and Systems class loaders).

The classes loaded by system class loader have visibility into classes loaded by its parents (i.e Extensions and Bootstrap class loaders).

If there were any sibling class loaders they cannot see classes loaded by each other. They can only see the classes loaded by their parent class loader.

Class loaders are hierarchical and use a delegation model when loading a class. Class loaders request their parent to load the class first before attempting to load it themselves. When a class loader loads a class, the child class loaders in the hierarchy will never reload the class again. Hence uniqueness is maintained. Classes loaded by a child class loader have visibility into classes loaded by its parents up the hierarchy but the reverse is not true.Two objects loaded by different class loaders are never equal even if they carry the same values, which mean a class is uniquely identified in the context of the associated class loader.

Dynamic class loading :
Dynamic loading is a technique for programmatically invoking the functions of a class loader at run time.
Class.forName (String className); //static method which returns a Class

static method returns the class object associated with the class name. The string className can be supplied dynamically at run time. Unlike the static loading, the dynamic loading will decide whether to load the class House at runtime based on a properties file and/or other runtime conditions. Once the class is dynamically loaded the following method returns aninstance of the loaded class. It’s just like creating a class object with no arguments.

class.newInstance (); //A non-static method, which creates an instance of a class (i.e. creates an object).

House myHouse = null ;
//myClassName should be read from a properties file or Constants interface.
String myClassName = "com.hiren.House" ;
Class houseClass = Class.forName(myClassName) ;
myHouse = (House) houseClass.newInstance();
myHouse.setArea(5000);

Posted by Unknown on 3:37 PM
Labels:


  • Runnable — waiting for its turn to be picked for execution by the thread schedular based on thread priorities.
  • Running: The processor is actively executing the thread code. It runs until it becomes blocked, or voluntarily
  • gives up its turn with this static method Thread.yield(). Because of context switching overhead, yield() should not be used very frequently.
  • Waiting: A thread is in a blocked state while it waits for some external processing such as file I/O to finish.
  • Sleeping: Java threads are forcibly put to sleep (suspended) with this overloaded method: Thread.sleep(milliseconds), Thread.sleep(milliseconds, nanoseconds);
  • Blocked on I/O: Will move to runnable after I/O condition like reading bytes of data etc changes.
  • Blocked on synchronization: Will move to Runnable when a lock is acquired.
  • Dead: The thread is finished working.
When a task invokes yield(), it changes from running state to runnable state. When a task invokes sleep(), it changes from running state to waiting/sleeping state.
Creation of Thread:

Threads can be used by either :
  • Extending the Thread class
  • Implementing the Runnable interface.
class Counter extends Thread {

//method where the thread execution will start
public void run(){
//logic to execute in a thread
}

//let’s see how to start the threads
public static void main(String[] args){
Thread t1 = new Counter();
Thread t2 = new Counter();
t1.start(); //start the first thread. This calls the run() method
t2.start(); //this starts the 2nd
thread. This calls the run() method
}
}
class Counter extends Base implements Runnable {

//method where the thread execution will start
public void run(){
//logic to execute in a thread
}

//let us see how to start the threads
public static void main(String[] args){
Thread t1 = new Thread(new Counter());
Thread t2 = new Thread(new Counter());
t1.start(); //start the first thread. This calls the run() method
t2.start(); //this starts the 2nd
thread. This calls the run() method
}
}

The runnable interface is preferred, as it does not require your object to inherit a thread because when you need multiple inheritance, only interfaces can help you. In the above example we had to extend the Base class so implementing runnable interface is an obvious choice. Also note how the threads are started in each of the different cases as shown in the code sample.

Daemon threads :
Daemon threads are sometimes called "service" threads that normally run at a low priority and provide a basic service to a program or programs when activity on a machine is reduced. An example of a daemon thread that is continuously running is the garbage collector thread. This thread, provided by the JVM, will scan programs for variables that will never be accessed again and free up their resources back to the system. A thread can set the daemon flag by passing a true boolean value to the setDaemon() method. If a false boolean value is passed, the thread will become a user thread. However, this must occur before the thread has been started.

Scheduling :
Java has a Thread Scheduler that monitors all running threads in all programs and decides which threads should be running and which are in line to be executed. There are two characteristics of a thread that the scheduler identifies in its decision process. One, the most important, is the priority of the thread, the other is the daemon flag. The scheduler's basic rule is if there are only daemon threads running, the Java Virtual Machine (JVM) will exit. New threads inherit the priority and daemon flag from the thread that created it. The scheduler determines which thread should be executed by analyzing the priorities of all threads. Those with the highest priority are allowed execution before any lower priority threads.
The scheduler can be of two flavors, preemptive or non-preemptive. Preemptive schedulers give a certain time-slice to all threads running on the system. The scheduler decides which thread is next to run and resume() that thread for some constant period of time. When the thread has executed for that time period it will be suspended() and the next thread scheduled will be resumed(). Non-preemptive schedulers decide which thread should run and run it until the thread is complete. The thread has full control of the system for as long as it likes. The yield() method is a way for a thread to force the scheduler to start executing another waiting thread. Depending on the system Java is running on, the scheduler can be either preemptive or non-preemptive.