Program 7 : Multi-threading
Create a Java program to illustrates multi-threaded programming with synchronized blocks, creating and running multiple threads using isAlive()
, and join()
:
Multi-threading using a synchronized
block to prevent race conditions. It creates three threads that share a single object. The isAlive()
and join()
methods are used to monitor and manage the threads from the main thread.
1. The Shared Resource (CallMe.java
)
This class has a method that will be shared by multiple threads. The synchronized(this)
block ensures that only one thread can execute the code within it at a time, preventing the output messages from getting jumbled.
// CallMe.java
// This is the shared resource that threads will access.
class CallMe {
public void call(String msg) {
// A synchronized block locks the 'this' object
synchronized(this) {
try { // Simulate processing time
Thread.sleep(1000);
System.out.print("[" + msg);
Thread.sleep(1000);
System.out.println("]");
} catch (InterruptedException e) {
System.out.println("Thread Interrupted");
} finally {
System.out.println( Thread.currentThread().getName()
+ " has Ended" )
}
}
}
}
2. The Thread Task (Caller.java
)
This class implements Runnable
. Each instance represents a task that will call the shared call()
method.
// Caller.java
// This class defines the task that each thread will execute.
class Caller implements Runnable {
private String msg;
private CallMe target;
public Caller(CallMe target, String msg) {
this.target = target;
this.msg = msg;
}
@Override
public void run() {
target.call(msg);
}
}
3. The Main Program (MultiThreadSyncDemo.java
)
This class creates the shared object and multiple threads. It demonstrates the use of isAlive()
to check thread status and join()
to wait for threads to complete.
// MultiThreadSyncDemo.java
// main class to orchestrate the multi-threaded execution.
public class MultiThreadSyncDemo {
public static void main(String[] args) {
// single, shared instance of the CallMe resource.
CallMe callMeTarget = new CallMe();
// Creating tasks
Caller task1 = new Caller(callMeTarget, "Hello");
Caller task2 = new Caller(callMeTarget, "Synchronized");
Caller task3 = new Caller(callMeTarget, "World");
// Creating the threads (workers) and assigning tasks
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task2);
Thread t3 = new Thread(task3);
// Starting the threads.
System.out.println("Starting threads...");
t1.start();
t2.start();
t3.start();
// isAlive() to check if threads are still running.
System.out.println("Checking thread status right after starting:");
System.out.println(t1.getName()
+ " is alive: " + t1.isAlive());
System.out.println(t2.getName()
+ " is alive: " + t2.isAlive());
System.out.println(t3.getName()
+ " is alive: " + t3.isAlive());
// join() to make the main thread wait for all other threads to finish.
System.out.println("\nMain thread is waiting for child threads to complete...");
try {
t1.join();
t2.join();
t3.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("\nChild threads have completed.");
// Checking the status again after join() returns.
System.out.println("Checking thread status after join():");
System.out.println(t1.getName()
+ " is alive: " + t1.isAlive()); // Will be false
System.out.println(t2.getName()
+ " is alive: " + t2.isAlive()); // Will be false
System.out.println(t3.getName()
+ " is alive: " + t3.isAlive()); // Will be false
System.out.println("\n Main thread exiting.");
}
}
Expected Output
The output shows that because of the synchronized
block, each call completes before the next one starts. The isAlive()
checks show the threads state before and after they've finished, and join()
ensures the main thread finishes last.
Starting threads...
Checking thread status right after starting:
Thread-0 is alive: true
Thread-1 is alive: true
Thread-2 is alive: true
Main thread is waiting for child threads to complete...
[Hello]
[Synchronized]
[World]
Child threads have completed.
Checking thread status after join():
Thread-0 is alive: false
Thread-1 is alive: false
Thread-2 is alive: false
Main thread exiting.