A thread is a path of execution within a program. As they have a common address space , they can share data. They also share the process running the program. A thread inherits the priority of its parent thread.

Multithreading                      
Java's multithreading support is centered on the java.lang.Thread class. The Thread class provides the capability to create objects of class Thread, each with its own separate flow of control. The Thread class encapsulates the data and methods associated with separate threads of execution and allows multithreading to be integrated within the object-oriented framework.
Java provides two approaches to creating threads. In the first approach, a subclass of class Thread  is created and override the run() method to provide an entry point into the thread's execution. When an instance of the Thread subclass is created, the program invoke its start() method to cause the thread to execute as an independent sequence of instructions. The start() method is inherited from the Thread class. It initializes the Thread object using the operating system's multithreading capabilities and invokes the run() method.
The approach to creating threads identified in the previous paragraph is very simple and straightforward. However, it has the drawback of requiring the Thread objects to be under the Thread class in the class hierarchy.
Java's other approach to creating threads does not limit the location of the Thread objects within the class hierarchy. In this approach, class implements the java.lang.Runnable interface. The Runnable interface consists of a single method, the run() method, which must be overridden by the class. The run() method provides an entry point into the thread's execution. In order to run an object of the class as an independent thread, it is passed as an argument to a constructor of class Thread
the join ( ) Method
The non-static join () method of class Thread lets one thread "join onto the end"
of another thread.

Thread t = new Thread ();
t.start ();
t.join ();
The preceding code takes the currently running thread (if this were in the main () method, then that would be the main thread) and joins it to the end of the thread referenced by t. This blocks the current thread from becoming runnable until after the thread referenced by t is no longer alive.

            There are many situations in which multiple threads must share access to common objects. For example, in a database system one thread to be updating a database record while another thread is trying to read it. Java enables to coordinate the actions of multiple threads using synchronized methods and synchronized statements.
An object for which access is to be coordinated is accessed through the use of synchronized methods. These methods are declared with the synchronized keyword. Only one synchronized method can be invoked for an object at a given point in time. This keeps synchronized methods in multiple threads from conflicting with each other.
The source code of the Thread Synchronization program.

public class AccountDanger implements Runnable {
private Account acct = new Account ();
public static void main (String [] args) {
AccountDanger r = new AccountDanger ();
Thread one = new Thread(r);
Thread two = new Thread(r);
one.setName ("Fred");
two.setName ("Lucy");
one.start ();
two.start ();
}
public void run () {
for (int x = 0; x < 5; x++) {
makeWithdrawal (10);
if (acct.getBalance () < 0) {
System.out.println ("account is overdrawn!");
}
}
}

private synchronized void makeWithdrawal (int amt) {
if (acct.getBalance () >= amt) {
System.out.println (Thread.currentThread ().getName () +
" is going to withdraw");
try {
Thread.sleep (500);
} catch (InterruptedException ex) { }
acct.withdraw (amt);
System.out.println (Thread.currentThread ().getName () +
" completes the withdrawal");
} else {
System.out.println ("Not enough in account for”
+ Thread.currentThread ().getName ()
+ “to withdraw " + acct.getBalance ());
}
}
}