Unit 4: Multithreading and Generic Programming




Multitasking vs Multithreading

Multitasking means the operating system runs multiple programs at the same time.

Example:

  • Music player
  • Web browser
  • Text editor (All running together)

Types:

  • Process-based multitasking
  • Each task is a separate process

Multithreading means a single program performs multiple tasks at the same time using threads.

Example:

In a browser:

  • One thread loads page
  • Another plays video
  • Another downloads file

Differences Between Multitasking and Multithreading

AspectMultitaskingMultithreading
Unit of executionProcessThread
MemorySeparate memoryShared memory
SpeedSlowerFaster
CommunicationDifficultEasy
ExampleMultiple applicationsMultiple tasks in one app

Thread Life Cycle

A thread goes through different states during execution.

Thread States:

  1. New - Thread object created
  2. Runnable - Ready to run
  3. Running - CPU executing thread
  4. Blocked / Waiting - Waiting for resource or signal
  5. Terminated (Dead) - Execution finished

Diagram (Text Representation)New → Runnable → Running → Waiting → Runnable → Dead

Creating Threads in Java

Java provides two main ways to create threads.

Method 1: Extending Thread Class

class MyThread extends Thread { public void run() { System.out.println("Thread running"); } public static void main(String args[]) { MyThread t = new MyThread(); t.start(); } }

Important:

  • start() creates a new thread
  • run() contains thread logic

Method 2: Implementing Runnable Interface

class MyRunnable implements Runnable { public void run() { System.out.println("Runnable thread"); } public static void main(String args[]) { Thread t = new Thread(new MyRunnable()); t.start(); } }

Advantage:

  • Supports multiple inheritance
  • More flexible

Synchronizing Threads

Synchronization prevents multiple threads from accessing shared data at the same time.

Problem Without Synchronization:

  • Data inconsistency
  • Wrong output

Synchronized Method

synchronized void display() { // critical section }

Synchronized Block

synchronized(this) { // critical code }

Benefit:

  • Thread safety
  • Prevents race condition

Inter-Thread Communication

Threads communicate with each other using:

  • wait()
  • notify()
  • notifyAll()

Example: Producer-Consumer problem

synchronized void produce() { wait(); } synchronized void consume() { notify(); }

Use:

  • Efficient resource sharing
  • Avoids busy waiting

Daemon Threads

Daemon threads run in background to support other threads.

Example:

  • Garbage Collector
  • Auto-save

Characteristics:

  • Runs in background
  • Automatically stops when user threads finish

Example:

Thread t = new Thread(); t.setDaemon(true); t.start();

Thread Groups

A thread group is a collection of threads.

Purpose:

  • Manage multiple threads together
  • Set priorities
  • Interrupt all threads at once

Example:

ThreadGroup tg = new ThreadGroup("MyGroup"); Thread t1 = new Thread(tg, "Thread1"); Thread t2 = new Thread(tg, "Thread2");

ThreadGroup Methods:

MethodUse
activeCount()Count active threads
interrupt()Stop all threads
getName()Group name

Conclusion

Multithreading in Java allows:

  • Faster execution
  • Efficient CPU usage
  • Responsive applications

Understanding thread creation, life cycle, synchronization, communication, daemon threads, and thread groups is essential for Java exams, interviews, and real-world systems.

Introduction to Generic Programming

Generic Programming in Java allows us to write a class or method that works with different data types while maintaining type safety.

Simple meaning: Write code once, use it for many data types (Integer, String, Double, etc.).

Without Generics (Problem):

ArrayList list = new ArrayList(); list.add(10); list.add("Hello"); // Runtime error possible

With Generics (Solution):

ArrayList<Integer> list = new ArrayList<Integer>(); list.add(10); // Only integers allowed

Benefits:

  • Compile-time error checking
  • No type casting
  • Cleaner and safer code

Generic Classes

A generic class is a class that can work with any data type, specified when creating its object.

Syntax:

class ClassName<T> { T variable; }
  • T → Type parameter (can be any name)

Example of Generic Class

class Box<T> { T value; void set(T value) { this.value = value; } T get() { return value; } }

Using Generic Class:

Box<Integer> b1 = new Box<Integer>(); b1.set(10); Box<String> b2 = new Box<String>(); b2.set("Java");

Advantages:

  • Same class works for multiple data types
  • Strong type checking
  • Code reusability

Generic Methods

A generic method is a method that introduces its own type parameter, independent of the class.

Syntax: < T > returnType methodName(T value)

Example of Generic Method

class Test { static <T> void display(T value) { System.out.println(value); } public static void main(String args[]) { display(10); display("Hello"); display(25.5); } }

Key Points:

  • Can be static or non-static
  • Can be inside normal or generic class
  • Type is decided at method call

Bounded Types (Bounded Type Parameters)

Bounded types restrict the type parameter to a specific class or its subclasses.

Simple meaning:

You can say:

“Only numbers are allowed, not strings.”

Upper Bounded Type (extends)

Used to restrict type to a class and its subclasses.

Example:

class Test<T extends Number> { T num; }

Allowed Types:

  • Integer
  • Float
  • Double

Not Allowed:

  • String
  • Character

Example Program:

class Calculator<T extends Number> { void show(T num) { System.out.println(num); } }

Multiple Bounds

A type parameter can extend one class and multiple interfaces.

class Test<T extends Number & Runnable> { }

Restrictions and Limitations of Generics

Generics have some important limitations.

Cannot Use Primitive Types

Not allowed:

Box<int> b;

Allowed:

Box<Integer> b;

Cannot Create Object of Type Parameter

Not allowed:

T obj = new T();

Static Members Cannot Use Type Parameter

Not allowed:

static T data;

Reason: Static members belong to class, not object.

Cannot Use instanceof with Generic Types

Not allowed: if(obj instanceof T)

Generic Arrays Are Not Allowed

❌ Not allowed:

T[] arr = new T[10];

Type Erasure

At runtime, Java removes generic type information.

Example:

ArrayList<Integer> list; ArrayList<String> list;

Both become:

ArrayList

Difference: Generic Class vs Generic Method

FeatureGeneric ClassGeneric Method
ScopeWhole classOnly method
Type parameterDefined at class levelDefined at method level
UsageObject creationMethod call

Conclusion

Generic Programming in Java:

  • Improves type safety
  • Reduces runtime errors
  • Enhances code reusability
  • Is widely used in Java collections

Understanding generic classes, generic methods, bounded types, and their limitations is essential for Java programming, exams, and interviews.