MultiThreaded Programming  «Prev  Next»

Lesson 3A time and place for multithreading
Objective Assess the Significance of Threads and when they are most useful.

When to use multithreading in Application

Multithreading[1] can be a powerful tool in Java programming. However, multithreading is not useful in every situation. To help you in determining whether to use threads, consider the following program needs that would necessitate the use of threads:
  1. The program performs a lengthy operation.
  2. There are operations that need to take place in the background
  3. There is a high-speed operation that needs to maximize system resources.

If your program has any of these characteristics then you should probably use threads to make things more efficient. Here are some real-world examples of those characteristics:

Time and place for Multithreading
1) A multithreaded program performing a lengthy operation might display a status indicator to give the user feedback as the operation is being carried out.
1) A multithreaded program performing a lengthy operation might display a status indicator to give the user feedback as the operation is being carried out.

2) A virus scanner may scan for virus in the background while you are working on other things.
2) A virus scanner may scan for a virus in the background while you are working on other things.


3) An animation program might use a thread to maximize system resources and establish a high animation frame rate.
3) An animation program might use a thread to maximize system resources and establish a high animation frame rate.

Design methods for Concurrent Algorithms

I want to first talk about design methods for concurrent algorithms, but I want to do it abstractly. Let me say that there will be plenty of code examples to give concreteness to the ideas that are presented here. In addition, I want to let you know that not every bit of computation can be made concurrent, no matter how hard you try. To save you the time of trying to take on too many impossible things in the course of your day, I have examples of the kinds of algorithms and computations. When any of those examples can be modified to allow for concurrent execution, I have included hints and tips about how to do that.
If you have sequential code that you want to transform into a concurrent version, you need to identify the independent computations that can be executed concurrently. The way you approach your serial code will influence how you reorganize the computations into a concurrent equivalent.
  1. One way is task decomposition, in which the computations are a set of independent tasks that threads can execute in any order.
  2. Another way is data decomposition, in which the application processes a large collection of data and can compute every element of the data independently.

Design Models for Concurrent Algorithms

If you have sequential code that you want to transform into a concurrent version, you need to identify the independent computations that can be executed concurrently. The way you approach your serial code will influence how you reorganize the computations into a concurrent equivalent.
  1. One way is task decomposition, in which the computations are a set of independent tasks that threads can execute in any order.
  2. Another way is data decomposition, in which the application processes a large collection of data and can compute every element of the data independently.

These two models are not the only possibilities, but I have found them to be the two most common. For other patterns of computation and how to transform them into concurrent algorithms.

One thing to keep in mind is that multithreaded programs are typically more complex than their non-multithreaded counterparts. This complexity makes it more important for you to only use threads when you are certain that a program would benefit from them. In the next lesson, you will learn how to create and use the Thread class.

Multithreaded vs. Non-Multithreaded Programs in Java: A Technical Distinction

In the realm of computer science, the concept of concurrency stands as a cornerstone in achieving efficient and responsive system behavior. Java, as a sophisticated and modern programming language, provides robust mechanisms to implement concurrent processing. Central to this discourse are the notions of multithreaded and non-multithreaded programs. Herein, we elucidate the technical differences between these two paradigms within the Java context.
  1. Fundamental Definition:
    • Multithreaded Programs: Multithreaded programs in Java deploy multiple threads of execution, either to perform distinct tasks concurrently or to distribute a single task across threads for parallel execution.
    • Non-Multithreaded Programs: Non-multithreaded programs, often termed single-threaded programs, utilize a single thread of execution. All tasks are executed sequentially by this singular thread.
  2. Concurrency and Parallelism:
    • Multithreaded Programs: They inherently support both concurrency (multiple tasks making progress over a period of time) and parallelism (multiple tasks being executed simultaneously). This is especially pronounced on multi-core processors where different threads can run on different cores concurrently.
    • Non-Multithreaded Programs: Such programs lack native support for parallelism. They execute tasks sequentially, implying that at any given instance, only one task makes progress.
  3. Responsiveness and Throughput:
    • Multithreaded Programs: By distributing tasks across threads, multithreaded programs can often achieve better responsiveness (especially in I/O-bound operations) and improved throughput, as CPU cycles can be efficiently utilized even when certain threads are waiting.
    • Non-Multithreaded Programs: The program's responsiveness is tied to the execution speed of the singular thread. Lengthy or blocking operations can hinder responsiveness, as other tasks await the completion of the current task.
  4. Complexity and Overhead:
    • Multithreaded Programs: Introducing multiple threads augments program complexity, necessitating mechanisms like synchronization, locking, and thread communication. There's also an overhead associated with thread management and context switching.
    • Non-Multithreaded Programs: These are generally simpler, with linear flow and absence of synchronization-related complexities. The overhead of managing multiple threads is non-existent.
  5. Data Sharing and Isolation:
    • Multithreaded Programs: Threads in a multithreaded program share the same process memory. While this facilitates easy data sharing, it also introduces risks like data races and necessitates synchronization mechanisms to ensure data integrity.
    • Non-Multithreaded Programs: With only one thread of execution, data races and concurrency-related issues are inherently avoided. Data sharing concerns are limited to standard program flow constructs.
  6. Use Cases:
    • Multithreaded Programs: Suited for applications requiring high responsiveness, CPU-bound operations benefitting from parallel execution, or scenarios like server applications where multiple client requests are handled simultaneously.
    • Non-Multithreaded Programs: Ideal for straightforward applications with linear workflows, or scenarios where the overhead and complexity of multithreading aren't justified.

While multithreaded programs in Java offer the allure of concurrent and parallel execution, boosting responsiveness and throughput, they come with the caveat of added complexity and potential pitfalls like data races. Non-multithreaded programs, with their linear and straightforward execution model, provide simplicity but might not fully harness the computational capabilities of modern hardware. An astute computer scientist weighs the merits and demerits of each paradigm, making informed decisions tailored to the application's needs and the underlying hardware architecture.


The difference between multithreaded and non-multithreaded programs in Java is worth clarifying. When I refer to a multithreaded Java program we are always talking about a program where there is explicit code to manage and create worker threads in addition to the main application thread.
Technically speaking, all Java programs are threaded since every program contains a main application thread. For a program to be multithreaded, however, it must contain more than one thread. The main application thread in a program is automatically created and managed by Java. You must explicitly create worker threads in a multithreaded program.

What exactly is a Java Thread?

The term thread is shorthand for thread of control, and a thread of control is, at its simplest, a section of code executed independently of other threads of control within a single program. Thread of control sounds like a complicated technical term, but it is really a simple concept, It is the path taken by a program during execution. This determines what code will be executed:
Question Does the if block get executed, or does the else block?
How many times does the while loop execute? If we were executing tasks from a "to do" list, much as a computer executes an application, what steps we perform and the order in which we perform them is our path of execution, the result of our thread of control.
Having multiple threads of control is like executing tasks from two lists. We are still doing the tasks on each "to do" list in the correct order, but when we get bored with the tasks on one of the lists, we switch lists with the intention of returning at some future time to the first list at the exact point where we left off.


Single-theaded Java programs that use synchronization may be slightly slower than they would be without synchronization. For early Java releases, synchronization was expensive. For any modern release, however, uncontended synchronization is pretty cheap.
  1. Lock coarsening
  2. Lock elision
  3. Adaptive Spin locking
  4. Biased locking



Java Threads Quiz Question

Consider the following code:
class MyThread extends Thread{
 int i = 0;
  public void run()   {
   while(true){
    if( i%2 == 0 ) System.out.println("Hello World");
   }
  }
}

What will be the output when this program is compiled and run from the command line? [Select 1 option: ]
  1. It will keep printing Hello World.
  2. It will print Hello World only once.
  3. This program will not even compile.
  4. This will compile but an exception will be thrown at runtime.
  5. It will compile and run but it will not print anything.


Answer: d
Explanation:
There is no problem with the program and there is no compiler error.
However, also note that there is no standard main() method. For this reason, the program cannot run from the command line. Make sure that you read the question properly.

[1]Multithreading: Multithreading is the capability of a program to have multiple paths of execution called threads.

SEMrush Software