0% found this document useful (0 votes)
3 views2 pages

Java MultiThreading Example Code

The document presents a Java program demonstrating multithreading using a synchronized method to print multiplication tables. It defines a PrintTable class with a synchronized print method that allows only one thread to execute at a time, while two MyThread instances are created to run concurrently. The output shows the order of thread execution and the multiplication results for the numbers 2 and 3.

Uploaded by

Thunder
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views2 pages

Java MultiThreading Example Code

The document presents a Java program demonstrating multithreading using a synchronized method to print multiplication tables. It defines a PrintTable class with a synchronized print method that allows only one thread to execute at a time, while two MyThread instances are created to run concurrently. The output shows the order of thread execution and the multiplication results for the numbers 2 and 3.

Uploaded by

Thunder
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

//MultiThreading

class PrintTable
{

synchronized void print(int n) //synchronized method allows only 1 thread at a time


{
Thread ref = [Link]();
String name = [Link]();
[Link](name);
// synchronized(this) //preferred way is to synchronize the block instead of complete method
{
if(n==2) //thread 0 with n=2 will be blocked and thread 1 will occupy lock
try{ wait(); } catch(Exception e){}
for (int i=1;i<=3;i++)
{
[Link](n*i);
try{ [Link](1000); } catch(Exception e){ }
}//for
notify(); //thread 1 will release the lock, thread 0 will access the shared resource
} //syn
} //print
} //class
//thread can be created by extending Thread class or runnable interface
class MyThread extends Thread
{ PrintTable p;
int n;
MyThread(PrintTable p, int n)
{
this.p = p;
this.n = n;
}
//override the run() exists in Runnable interface
public void run()
{
[Link](n);
}

}
class Test1{
public static void main(String args[])
{
PrintTable p = new PrintTable();
MyThread t1 = new MyThread(p,2);
MyThread t2 = new MyThread(p,3);

[Link]();
[Link]();
}
}

Output:
Thread-0
Thread-1
3
6
9
2
4
6

Common questions

Powered by AI

The wait() method, when called within a synchronized block, causes the current thread to release its lock on the object and enter a waiting state until another thread issues a notify() on the same object. This mechanism prevents the current thread from proceeding, effectively blocking its execution. This allows another thread to acquire the lock and proceed with execution, ensuring that shared resources are used efficiently. In the given example, if thread 0 attempts to execute with n = 2, it will call wait(), subsequently blocking its flow until thread 1 completes its execution and calls notify().

The run() method in the thread class is an implementation that fulfills the contract defined by the Runnable interface. The Runnable interface requires implementing classes to provide a concrete definition of the run() method, which contains the code to be executed by the thread. In the MyThread class, which extends the Thread class, the run() method is overridden to invoke the print() method of the PrintTable instance, ensuring that the intended sequence of operations is executed by the thread .

If the call to wait() is omitted in the synchronized block of the PrintTable class, the initial control flow and intended resource access coordination will change. Both threads would attempt to proceed with printing immediately upon obtaining the lock, which might result in overlapping execution and disrupted intended sequence operations. The intended synchronization, where thread 1 completes before thread 0 can proceed, would be compromised, potentially leading to interleaved outputs or a sequence not anticipated or desired by the synchronization design .

The synchronized keyword in Java's PrintTable class ensures that only one thread can access the synchronized method at any given time. It locks the object for any thread attempting to access the method, blocking other threads until the lock is released. This control prevents thread interference and memory consistency errors by maintaining an orderly access, crucial for tasks involved in modifying shared resources, such as printing a table with sensitive timing and sequence dependence .

The Thread.sleep() method is used within MyThread's run method to introduce a delay between executions of sequential operations within the for loop. This planned pausing simulates real-world timing inconsistencies and helps avoid burdening the CPU continuous execution, providing a controlled and observable output. In the PrintTable's context, it ensures that threads pause momentarily between printing each line of the table, resulting in a spaced output appearance over time .

In the MyThread class, method overriding is used to provide a specific implementation of the run() method inherited from the Thread class. The significance lies in enabling polymorphic behavior where the start() method, called on a MyThread instance, executes the customized run() method, thus executing the specific sequence of operations defined for the MyThread object. This redefinition allows for each thread instance to perform actions distinct to its context, which in this case involves calls to the PrintTable's synchronized method using different integer arguments .

The usage of notify() in synchronized blocks influences thread access to shared resources by signaling one of the waiting threads to resume execution. Once a thread finishes its task and calls notify(), it effectively releases the lock, allowing another waiting thread to acquire it and access the shared resources. This coordination ensures orderly and regulated access to shared resources, as demonstrated when thread 1 calls notify() after its execution, which permits thread 0 to acquire the lock and proceed .

The concept of a shared resource is demonstrated in the Test1 class through the PrintTable instance passed to both MyThread objects. This single instance acts as a shared resource between threads, highlighting the significance of synchronization in managing concurrent access to shared data. This setup exemplifies real-world scenarios where multiple threads must utilize a common object safely and efficiently, necessitating techniques that control and coordinate access to prevent collisions and data inconsistencies in shared resources .

Choosing to extend the Thread class over implementing the Runnable interface is usually based on specific requirements. When extending the Thread class, a direct subclass is created, allowing the programmer to override thread behavior, which can be beneficial if there is a need to modify or enhance the threading mechanisms. Additionally, it simplifies thread initiation by calling start() on an instance of the class directly. However, this method inherits from one class only, limiting inheritance capabilities, unlike the Runnable interface, which allows for multiple inheritance paths. The Test1 example extends the Thread class potentially for ease of implementation and direct control over the thread behavior .

Synchronized blocks are generally preferred over synchronized methods because they allow for more fine-grained control over synchronization. This approach locks only the critical section of the code needed to be executed by a single thread at a time, improving performance and reducing overhead by allowing other threads to execute non-critical code outside the synchronized block. In contrast, synchronizing an entire method locks the whole method, potentially leading to thread contention and decreased efficiency .

You might also like