MultiThreaded Programming  «Prev  Next»

Lesson 2Multithreading basics
ObjectiveExplore the Basics of Threads and Multithreaded Programming

Basics of Threads and Multithreaded Programming

Multithreading Basics in Java

You might be curious as to how multiple threads can execute concurrently in a Java program when your computer only has one physical processor. The roots of multithreading actually have more to do with multitasking operating systems rather than Java.
Multitasking operating systems know how to intelligently divide processor time and share it among multiple applications.
Each application is given a small "slice" of processor time, which gives the illusion that all applications have the processor to themselves.
Threads work similarly to these multitasked applications in that they are each given a slice of processor time to execute. However, threads can not run independently and must always execute alongside a program's main thread and memory space, which is also known as a process.

The word multithreading can be translated as multiple threads of control or multiple flows of control. While a traditional UNIX process always has contained and still does contain a single thread of control, multithreading (MT) separates a process into many execution threads, each of which runs independently.
  1. Multithreading your code can
  2. Improve application responsiveness
  3. Use multiprocessors more efficiently
  4. Improve program structure
  5. Use fewer system resources

Java's built-in Support for multithreaded Programming

Unlike some computer languages, Java provides built-in support for multithreaded programming. A multithreaded program contains two or more parts that can run concurrently. Each part of such a program is called a thread, and each thread designates separate path of execution. Thus, multithreading is a specialized form of multitasking. You are almost certainly acquainted with multitasking because it is supported by virtually all modern operating systems. However, there are two distinct types of multitasking:
  1. process-based and
  2. thread-based.
It is important to understand the difference between the two. For many readers, process-based multitasking is the more familiar form. A process is, in essence, a program that is executing. Thus, process-based multitasking is the feature that allows your computer to run two or more programs concurrently. For example, process-based multitasking enables you to run the Java compiler at the same time that you are using a text editor or visiting a web site. In process-based multitasking, a program is the smallest unit of code that can be dispatched by the scheduler.


Multitasking occurs at the application level, meaning that multiple applications are allowed to run simultaneously. Multithreading occurs within a single application, and provides support for multiple threads of execution within an application.
A multithreaded program is comprised of individual threads that execute concurrently. A thread is a single sequence of code executing within a program. Threads give multithreaded programs multiple paths of execution, which means that the threads all execute at the same time. Multiple threads share the same address space, therefore they can access the same objects. Multithreaded programs contain a main thread that is responsible for executing the main program code. Additional threads are known as worker threads and typically perform subordinate tasks to help out the main thread.
A good example of a multithreaded program is one that performs a lengthy operation such as sorting records in a database or calculating prime numbers. The lengthy operation is performed in a worker thread, which frees the main program thread to do other things, such as respond to user input. The following figures illustrate this process:


1) The main application thread begins executing
1) The main application thread begins executing

2) A worker thread is started to carry out a lengthy operation
2) A worker thread is started to carry out a lengthy operation

3) Both threads execute concurrently
3) Both threads execute concurrently


4) The calculation thread finishes and returns the result to the application thread
4) The calculation thread finishes and returns the result to the application thread

5) The application thread finishes when the application is shut down
The application thread finishes when the application is shut down



Main Application Thread in Java

What is guaranteed by the JVM with respect to threads? [ Select 2 options: ]
  1. If a higher priority thread is in ready to run state then a lower priority thread will not run till the higher priority thread ends.
  2. CPU time is distributed to the threads according to thread priority.
  3. It is usually the operating System, which decides which thread to run when and for how much time.
  4. Threads in Java are usually System dependent.


Answer: c, d
Explanation: Simply put, there is no guarantee which thread will run when and for how much time. In some operating systems like Windows, CPU time is given to threads in ratio of their priority.
While in other operating systems like Unix, a lower priority thread executes only after higher priority thread ends.

Consider the code shown below:
public class Outer {
 public A a1 = new A();
 public B b1 = new B();
 class A { // inner class
  public synchronized void doIt() {
   try {
    wait();  // line 1:
    System.out.println("done");
   } catch (Exception e) {}
  }
 }	
 class B extends Thread {
  public void run() {
   a1.doIt();
  }
 }
 public Outer() throws Exception {
  b1.start(); // B thread
  Thread.sleep(1000);
  // line 2: insert code here
 }
 public static void main(String[] args) throws Exception {
  new Outer();
 }
}

Assume that you have run the above program. The b1 thread has just executed LINE1 and the thread that called b1.start() is about to call.
What can you insert at LINE LINE 2, so that the program will print done and exit? [Select 1 option]
  1. synchronized(this){ this.notifyAll(); }
  2. synchronized(b1){ b1.notifyAll(); }
  3. synchronized(a1){ a1.notifyAll(); }
  4. synchronized(a1){ Thread.interrupt(); }
  5. this.getCurrentThread().interrupt();


Answer: c
Explanation: It is given that the b1 thread has just executed LINE1. Now, observe that the doIt() method of A is synchronized, which means whichever thread enters this method, that thread must acquire the lock for the A object referred to by a1.
In this case, it is the B thread that has called the doIt() method. This thread then calls wait() (same as this.wait()), which means B thread will wait till some other thread calls a notify() or notifyAll() on the same A object. Therefore, the main thread, (this is the same thread that has called the constructor of TestClass) must call a1.notifyAll() or a1.notify().
In the next lesson, you will assess the significance of threads and when they are most useful.