Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

Java Inheritance, Polymorphism and Exception Handling: A Comprehensive Example, Lecture notes of Computer Science

An in-depth exploration of various Java programming concepts, including inheritance, polymorphism, method overriding, abstract classes, interfaces, exception handling, and multithreading. It includes practical examples using classes such as Shapes, Triangle, Room, BedRoom, A, B, and Series, as well as interfaces like Series. Students and developers can use this document as study notes, lecture notes, summaries, or as a reference for understanding these essential Java concepts.

Typology: Lecture notes

2021/2022

Uploaded on 10/02/2022

rohini-g
rohini-g 🇮🇳

1 document

1 / 20

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
ECR
Page 1
Inheritance
Inheritance Basics
Inheritance is one of the basic principles of object-oriented programming. A class that is inherited by
is called superclass. The class that does the inheritance is called subclass. It inherits all the variables
and methods defined by the superclass and adds its own unique elements.
Java supports inheritance by using the keyword extends. The general form of a class declaration that
inherits a superclass is given below:
class subclass-name extends superclass-name {
// body of the class
}
//Demonstrate single inheritance
class Shape{
int height, width;
void showDim() {
System.out.println(“Width = “ +width + “Height =”+height); } }
class Triangle extends Shape{
String style;
void showStyle(){
System.out.println(“Triangle is ” +style); }
int area() {
return(height*width /2); } }
class InheritDemo {
public static void main(String args[]) {
Triangle t1 = new Triangle();
Triangle t2 = new Triangle();
t1.height=4;
t1.width=6;
t1.style=”filled”;
t2.height=8;
t2.width=12;
t2.style=”outlined”;
t1.showDim();
t1.showStyle();
System.out.println(“Area =”+t1.area());
t2.showDim();
t2.showStyle();
System.out.println(“Area =”+t2.area()); } }
The class Shapes contains two members namely height and width and a method showDim(). The
class triangle inherits all the members and methods of the class Shape and it has its own member
named style and methods named area() and showStyle().
Member Access and Inheritance
All the public members of the base class are inherited by the derived classes where as the members
declared with the modifier private cannot be accessed by the derived class. The following example
program will not be compiled
class Shapes {
private int height;
private int width;
void showDim() {
System.out.println(“Width = “ +width + “Height =”+height); } }
class Triangle extends Shape {
Sting style;
Output
Height = 4 Width = 6
Triangle is filled
Area =12
Height = 8 Width = 12
Triangle is outlined
Area =48
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14

Partial preview of the text

Download Java Inheritance, Polymorphism and Exception Handling: A Comprehensive Example and more Lecture notes Computer Science in PDF only on Docsity!

ECR

Inheritance Inheritance Basics Inheritance is one of the basic principles of object-oriented programming. A class that is inherited by is called superclass. The class that does the inheritance is called subclass. It inherits all the variables and methods defined by the superclass and adds its own unique elements. Java supports inheritance by using the keyword extends. The general form of a class declaration that inherits a superclass is given below: class subclass-name extends superclass-name { // body of the class } //Demonstrate single inheritance class Shape{ int height, width; void showDim() { System.out.println(“Width = “ +width + “Height =”+height); } } class Triangle extends Shape{ String style; void showStyle(){ System.out.println(“Triangle is ” +style); } int area() { return(height*width /2); } } class InheritDemo { public static void main(String args[]) { Triangle t1 = new Triangle(); Triangle t2 = new Triangle(); t1.height=4; t1.width=6; t1.style=”filled”; t2.height=8; t2.width=12; t2.style=”outlined”; t1.showDim(); t1.showStyle(); System.out.println(“Area =”+t1.area()); t2.showDim(); t2.showStyle(); System.out.println(“Area =”+t2.area()); } }

The class Shapes contains two members namely height and width and a method showDim(). The class triangle inherits all the members and methods of the class Shape and it has its own member named style and methods named area() and showStyle(). Member Access and Inheritance All the public members of the base class are inherited by the derived classes where as the members declared with the modifier private cannot be accessed by the derived class. The following example program will not be compiled class Shapes { private int height; private int width; void showDim() { System.out.println(“Width = “ +width + “Height =”+height); } } class Triangle extends Shape { Sting style;

Output Height = 4 Width = 6 Triangle is filled Area = Height = 8 Width = 12 Triangle is outlined Area =

ECR

int area() { return width * height /2; // Error !Private members cant be accessed } } This program will not compile because width and height can not be inherited by the derived class since they are private. Constructors and Inheritance Both superclasses and subclasses can have their own constructors. The constructor of the superclass constructs the superclass portion of the object and that of the subclass constructs the subclass part. When only the subclass defines a constructor, it just constructs the object of the subclass. The superclass portion of the object is constructed by calling the default constructor. class Shape{ int height, width; void showDim() { System.out.println(“Width = “ +width + “Height =”+height); } } class Triangle extends Shape { Triangle(String s, int h, int w) { style=s; height =h; width=w; } void showStyle(){ System.out.println(“Triangle is ” +style); } int area() {return(height*width/2); } } class ConDemo { public static void main(String args[]) { Triangle t1 = new Triangle(“filled”, 4, 6); Triangle t2 = new Triangle(“outlined”, 8,12); t1.height=4; t1.width=6; t1.style=”filled”; t2.height=8; t2.width=12; t2.style=”outlined”; t1.showDim(); t1.showStyle(); System.out.println(“Area =”+t1.area()); t2.showDim(); t2.showStyle(); System.out.println(“Area =”+t2.area()); } }

The constructor Triangle() can be used to initialize objects of the derived class but it can not be used to initialize the objects of the base class.

Use of super() When both superclass and subclass define constructors, the process is bit complicated. The subclass constructor uses the keyword super to invoke the constructor of the superclass. The keyword super can be used only within the derived class and if included, it must always be the first statement executed inside a subclass constructor. //To demonstrate super() class Room { int length, breadth; Room(int x, int y) { length=x; breadth=y; } int area() { return(length*breadth); }}

Output Height = 4 Width = 6 Triangle is filled Area = Height = 8 Width = 12 Triangle is outlined Area =

ECR

Triangle() { super(); style=”none”; } class Triangle extends Shape { Triangle(String s, int h, int w) { super(int h, int w); style=s; void showStyle(){ System.out.println(“Triangle is ” +style); } int area() {return(height*width/2); } } class colTriangle extends Triangle { String colr; colTriangle(String s1, String s2, int x, int y) { super(s2, x,y); colr=s1; } void showColor(){ System.out.println(“Color is ” +colr);} } class MulDemo { public static void main(String args[]) { colTriangle t1 = new Triangle(“blue”, “filled”, 4, 6); Triangle t2 = new Triangle(“red”, “outlined”, 8,12); t1.showDim(); t1.showStyle(); t1.showColor(); System.out.println(“Area =”+t1.area()); t2.showDim(); t2.showStyle(); t1.showColor(); System.out.println(“Area =”+t2.area()); } }

Method Overriding In a class hierarchy when a method in a subclass has the same return type and signature as a method in it’s superclass, then the method in the subclass is said to override the method in the superclass. when a overridden method is called from within a subclass, it will always refer to the version of that method defined by the subclass. The version of the method defined by the superclass will be hidden. //Demonstrate method overriding class A { int i,j; A(int x, int y) { i=x, j=y; } void show() { System.out.println(“Values of i and j are “ +i+ “ ” +j); } } class B extends A { int k; B(int x, int y, int z) { super(x,y); k=z; } void show() { System.out.println(“”k= ”+k); } } class overrideDemo{ public static void main(String args[]){ B ob1=new B(10,20,30); Ob1.show() //refers t the function written in the subclass } } The show() in the subclass overrides the show() in the superclass. If we want to access the show() of superclass we can use the super() as follows:

Output Height = 4 Width = 6 Triangle is filled Color is blue Area = Height = 8 Width = 12 Triangle is outlined Color is red Area =

Output k= 30

ECR

B(int x, int y, int z) { super(x,y); k=z; } void show() { super(); System.out.println(“”k= ”+k); } } Abstract Methods and Classes If we modify a method as final we ensure that the method is not redefined in a subclass. Java allows us to do something that is exactly opposite to this. That is, we can indicate a method must always be redefined in a subclass, thus making overriding compulsory. This is done using the modifier keyword abstract. Example: abstract class Shape { ........ ........ abstract void show() { ........ } }

While using abstract classes, we must satisfy the following conditions:  Abstract classes can not be used to instantiate objects directly. For example: Shape s1=new Shape() is illegal because Shape is an abstract class according to the above example.  The abstract methods of an abstract class must be redefined in its subclass  We can not declare abstract constructors or abstract static methods. Final variables and methods All methods and variables can be overridden by the subclasses. If we wish to prevent overriding the members if superclass we can declare them as final using the keyword final as modifier. Example final int size = 100; final void showStatus() Making a method final ensures that the functionality defined in this method will never be altered in any way. Similarly, the value of a final variable can never be changed. Final variables behave like class variables and they do not take any space on individual objects of the class. class A{ final void meth() { System.out.println(“This is a final method”); } Class B extends A { void meth() { // Error can’t override!!! } }

Using final with Inheritance The keyword final has three uses. First, it can be used to create the equivalent of a named constant. Second, it can be used to Prevent Overriding, third, Using final to Prevent Inheritance. Using final to Prevent Overriding While method overriding is one of Java’s most powerful features, there will be times when you will want to prevent it from occurring. To disallow a method from being overridden, specify final as a modifier at the start of its declaration. Methods declared as final cannot be overridden. The following fragment illustrates final. class A {

Output Values of i and j 10 20 k= 30

ECR

source file. The classes declared within that file will belong to the specified package. Since a package specifies a namespace, the names of the classes inside it become the part of the namespace. The general form of package statement is package pkg; where pkg is the name of the package. Example: package myPack; Accessing a Package It is to be noted that a Java system package can be accessed either using a fully qualified class name for using a shortcut approach through the import statement. We use import statement when there are many references to a particular package or the package name is too long and unwieldy. The same approach can be used to access the user-defined packages as well. The import statement can be used to search a list of packages for a particular class. The general form of import statement for searching a class is : import package1 [.package2] [.package3].classname; Here package1 is the name of the top level package, package2 is the name of the package that is inside the pacakge1 , and so on. We can have any number of packages in a package hierarchy, Finally, the explicit classname is specified. Note that the statement must end with a semicolon and the import statement should appear before any class definitions in a source file. Multiple import statements are allowed. Following is an example of importing a particular class : import firstPackage.secondPackage.MyClass; After using this statement, all the members of the class MyClass can be directly accessed using the class name or its objects directly without using the package name.

We can also use another approach as follows import packagename.*; Here, packagename may denote a single package or a hierarchy of packages. The * indicate that the compiler should search this entire package hierarchy when it encounters a class name. This implies that we can access all classes contained in the above package directly.

Adding a class to a package. It is simple to add a classs to an existing package. For example consider package p1; public class ClassA { ….. } The above package p1 contains one class ClassA. Suppose we want to add another class ClassB to this package. This can be done as follows :

  1. Define the class and make it public.
  2. Place the package statement p1 before the class defintion as follows package p1; public class ClassB { …… }

ECR

Packages and Member Access The visibility of an element is determined by its access specification—private, public, protected or by default. If a member has no explicit access modifier, then it is visible within its package and not outside the package. The members which are declared s public are visible everywhere including different classes of different package. There is no restriction on their use or access. A private member is available only to the other members of its class. A member specified as protected is accessible within its package and to all subclasses including subclasses in another package. Class Member Access Private Member Default Member Protected Member Public Member Visible within same class

Yes Yes Yes Yes

Visible within same package by subclass

No Yes Yes Yes

Visible within same package by non-subclass

No Yes Yes Yes

Visible within different package by subclass

No No Yes Yes

Visible within different package by non-subclass

No No No Yes

Built-in Packages Java defines a large number of standard classes that are available to all programs. This cass library is referred to as the Java API (Application Programming Interface) The Java. API is stored in packages. At the top of the package hierarchy is java.

Subpackage Description java.lang Langage support classes. These are classes that Java compiler itself uses and therefore they are automatically imported. They include classes for primitive types, strings, math functions, threads and exceptions. java.util Language utility classes as vectors, hash tables, random numbers, date, etc. java.io Input/output support classes. They provide facilities for the input and output of data java.awt Set of classes for implementing graphical user interface. They include classes for windows, buttons, lists, menus and so on. java.net Classes for networking. They include classes for communicating with local computers as well as with internet servers. java.applet Classes for creating and implementing applets

Interfaces Interfaces are syntactically similar to classes, but they lack instance variables, and their methods are declared without any body. An interface doesn’t provide any implementation. To implement interface, classes must provide bodies for the methods described by the interface. Two classes may implement the same interface in different ways but each class supports the same set of methods. By providing interface keyword, Java allows the programmers to utilize “One interface, multiple methods” aspect of polymorphism. This is the general form of an interface: access interface name {

ECR

for(int i=0; i<5; i++) System.out.println(“Next value is ”+ob.getNext()); System.out.println(“\n Resetting”); ob.reset(); for(int i=0; i<5; i++) System.out.println(“Next value is ”+ob.getNext()); System.out.println(“\n Starting at 100”); ob.setStart(100); for(int i=0; i<5; i++) System.out.println(“Next value is ”+ob.getNext()); } }

Using Interface References We can create interface reference variables. Such a variable can refer to an object that implements its interface. When a method on an object is called through an interface reference, the version of the version of the method implemented by the object is executed.

// Demonstrate interface references public interface Series { int getNext(); void reset(); void setStart(int x); } class ByTow implements Series { int start, val;

ByTwo() { start=0; val=0; }

public int getNext() { val+=2; return val; } public void reset() { val=start; } public void setStart(int x) { start=x; val=x; } } class SDemo2 { public static void main(String args[]) { ByTwo two = new ByTwo(); Series ob; Ob=two; for(int i=0; i<5; i++) System.out.println(“Next value is ”+ob.getNext()); } }

Extending an Interface One interface can inherit another by use of the keyword extends. The syntax is the same as for inheriting classes. When a class implements an interface that inherits another interface, it must provide implementations for all methods defined within the interface inheritance chain. Following is an example: // One interface can extend another. interface A { void meth1(); void meth2(); }

ECR

// B now includes meth1() and meth2() -- it adds meth3(). interface B extends A { void meth3(); } // This class must implement all of A and B class MyClass implements B { public void meth1() { System.out.println("Implement meth1()."); } public void meth2() { System.out.println("Implement meth2()."); } public void meth3() { System.out.println("Implement meth3()."); } } class IFExtend { public static void main(String arg[]) { MyClass ob = new MyClass(); ob.meth1(); ob.meth2(); ob.meth3(); } }

Exception Handling Exception Handling Fundamentals A Java exception is an object that describes an exceptional (that is, error) condition that has occurred in a piece of code. When an exceptional condition arises, an object representing that exception is created and thrown in the method that caused the error. All exception classes are derived from a class called Throwable. There are two direct subclasses of Throwable class: Exception and Error. Java exception handling is managed via five keywords: try , catch , throw , throws , and finally. Program statements that require monitoring are contained within a try block. If an exception occurs within the try block, it is thrown. The code can catch this exception (using catch ) and handle it in some rational manner. System-generated exceptions are automatically thrown by the Java run-time system. To manually throw an exception, the keyword throw can be used. Any exception that is thrown out of a method must be specified as such by a throws clause. Any code that absolutely must be executed after a try block completes is put in a finally block.

Using try and catch This is the general form of an exception-handling block: try { // block of code to monitor for errors } catch ( ExceptionType1 exOb ) { // exception handler for ExceptionType } catch ( ExceptionType2 exOb ) { // exception handler for ExceptionType } // ... finally { // block of code to be executed after try block ends } Here, ExceptionType is the type of exception that has occurred. When an exception is thrown, it is caught by the corresponding catch statement which then processes the exception. When no exception is thrown, try block ends normally and catch statements are bypassed. Thus catch statements are executed only if an exception is thrown.

ECR

Catching Subclass Exceptions A catch clause for a superclass will also match any of its subclasses. Since the superclass of all exceptions is Throwable, to catch all possible exception, we can use Throwable. If subclass exception has to be caught, it must be put first in the catch sequence. class EDemo4 { public static void main(String args[]) { int nr[] {4, 8, 16, 32, 64, 128, 265, 512}; int dr[] {2, 0, 4, 4, 0, 8}; for(int i=0; i<nr.length; i++) { try { System.out.println( nr[i] +”/” + dr[i] +”=” +nr[i]/dr[i]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(“No Matching Element ”); } catch (Throwable e) { System.out.println(“Some Exception occurred ”); } } } }

Nesting of try Blocks One try block can be nested within another. An exception generated by the inner try block is not caught by the catch statement associated with that try. class EDemo5 { public static void main(String args[]) { int nr[] {4, 8, 16, 32, 64, 128, 265, 512}; int dr[] {2, 0, 4, 4, 0, 8}; try { for(int i=0; i<nr.length; i++) { try { System.out.println( nr[i] +”/” + dr[i] +”=” +nr[i]/dr[i]); } catch (ArithmeticException e) { System.out.println(“Can’t divide by zero ”); } } } catch (ArrayIndexOutOfBounds e) { System.out.println(“No matching element ”); System.out.println(“Fatal Error \n Program terminated ”);} } }

In the example given above, if division by zero exception is occurred, it is handled by the inner catch block and the program execution continues. However, the array boundary error is caught by the outer catch, which causes the program to terminate.

Throwing an Exception It is possible to throw an exception manually using the throw statement. // manually throw and exception calss ThrowDemo { public static void main(String args[]) { try{ System.out.println(“Before throw. ”); throw new ArithmeticException(); } catch (ArithmeticException e) { System.out.println(“Exception caught ”); } System.out.println(“After try /catch block ”); }

Output: 4/2 = 2 Some Exception Occurred 16/4= 32/4= Some Exception Occurred 128/8= 16 No Matching Element No Matching Element

Output: 4/2 = 2 Can’t divide by zero 16/4= 32/4= Can’t divide by zero 128/8= 16 No Matching Element Fatal Error Program terminated

Output: Before throw. Exception caught After try/catch block

ECR

Rethrowing an Exception An exception caught by catch statement can be rethrown so that it can be caught by an outer catch. The reason for rethrowing is to allow multiple handlers.

The Throwable Class All exceptions are subclasses of Throwable. Throwable supports several methods. The commonly used methods defined by Throwable class are listed below:

Method Description Throwable fillinStackTrace() Returns a Throwable object that contains complete stack trace String getLocalizedMessage() Returns a localized description of the exception void printStackTrace() Displays the stack trace void printStackTrace(PrintStream s) Sends the stack trace to specified stream void printStackTrace(PrintWriter s) Sends the stack trace to specified stream String toString() Returns the string object containing a complete description of the exception. This method is called by println() when outputting Throwable object. Java’s Built-in Exceptions Inside the standard package java.lang , Java defines several exception classes. The most general of these exceptions are subclasses of the standard type RuntimeException. As previously explained, these exceptions need not be included in any method’s throws list. In the language of Java, these are called unchecked exceptions because the compiler does not check to see if a method handles or throws these exceptions. Exceptions defined by java.lang that must be included in a method’s throws list if that method can generate one of these exceptions and does not handle it itself. These are called checked exceptions.

Exception Meaning

ArithmeticException Arithmetic error, such as divide-by-zero.

ArrayIndexOutOfBoundsException Array index is out-of-bounds.

ArrayStoreException Assignment to an array element of an incompatible type.

ClassCastException Invalid cast.

EnumConstantNotPresentException An attempt is made to use an undefined enumeration value

IllegalArgumentException Illegal argument used to invoke a method. IllegalMonitorStateException Illegal monitor operation, such as waiting on an unlocked thread. IllegalStateException Environment or application is in incorrect state. IllegalThreadStateException Requested operation not compatible with current thread state. IndexOutOfBoundsException Some type of index is out-of-bounds. NegativeArraySizeException Array created with a negative size. NullPointerException Invalid use of a null reference. NumberFormatException Invalid conversion of a string to a numeric format. SecurityException Attempt to violate security. StringIndexOutOfBounds Attempt to index outside the bounds of a string. TypeNotPresentException. Type not found UnsupportedOperationException An unsupported operation was encountered The unchecked exceptions defined in java.lang

ECR

actually implement anything—it is their existence in the type system that allows us to use them as exceptions. The Exception class does not define any methods of its own. It inherits those methods provided by Throwable. //Demonstrate user-defined exception handling import java.lang.Exception class MyException extends Exception { MyException(String mag) super(msg); } } class UserException { public static void main(String args[]) { int x=5, y=1000; try{ float z = float(x)/float(y); if(z<0.01) { throw new MyException(“Number is too small”); } } catch(MyException e) { System.out.println(“Caught My Exception”); System.out.println(e.getMessage()); } finally{ System.out.println(“I am always here”; } } }

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 defines a separate path of execution. Thus, multithreading is a specialized form of multitasking.

Multithreading Fundamentals There are two distinct types of multitasking: process-based and thread-based. A process is a program that is executing. A process-based multi-tasking allows the computer to run two or more programs concurrently. In thread-based multi tasking environment, a single program can perform two or more tasks at the same time. The advantage of multithreading is that it makes one to write efficient programs which utilize the idle time that is present in most of the programs. I/O devices are much slower than the CPU. Sometimes, a program spends majority of its execution time waiting to send or receive the information to or from a device. By using multithreading, the program can execute another task. Threads exist in several states. A thread can be running. It can be ready to run as soon as it gets CPU time. A running thread can be suspended , which temporarily suspends its activity. A suspended thread can then be resumed , allowing it to pick up where it left off. A thread can be blocked when waiting for a resource. At any time, a thread can be terminated , which halts its execution immediately. Once terminated, a thread cannot be resumed.

The Thread Class and Runnable Interface Java’s multithreading system is built upon the Thread class, its methods, and its companion interface, Runnable. Thread encapsulates a thread of execution. Since you can’t directly refer to the ethereal state of a running thread. To create a new thread, the program will either extend Thread or

Output: Caught My Exception Number is too small I am always here

ECR

implement the Runnable interface. The Thread class defines several methods that help manage threads. Few of them are listed below:

Method Meaning final String getName () Obtain a thread’s name. final int getPriority () Obtain a thread’s priority. final isAlive() Determine if a thread is still running. final void join() Wait for a thread to terminate. void run() Entry point for the thread. static void sleep(long milliseconds) Suspend a thread for a period of time. void start() Start a thread by calling its run method.

All processes have at least one thread of execution, which is usually called the main thread, because it is the one that is executed when the program begins. From the main thread other threads can be created.

Creating a Thread There are two methods in Java by which we can create threads.

  1. By implementing Runnable interface.
  2. By extending Thread class. The Runnable interface defines only one method called run() // Demonstrate creation of a Thread class X implements Runnable { public void run() { for(int i=0; i<=5; i++) System.out.println(“I from thread X = ”+ i); } } class ThreadDemo { public static void main(String args[]) { X rn = new X(); Thread t1=new Thread(rn); t1.start(); System.out.println(“End of main”); } }

Creating Multiple Threads The above program creates a single thread. Multiple threads can be created in same way. The following program illustrates creation of multiple threads. System.out.println(“Square of ”+ i + “ = ”+ ii); } } class Cube implements Runnable { public void run() { for(int i=1; i<=5; i++) System.out.println(“Cube of ”+ i + “ = ”+ ii*i); } } class ThreadDemo1 { public static void main(String args[]) { Square s = new Square(); Cube c = new Cube(); Thread t1=new Thread(s); Thread t2=new Thread(c); t1.start(); t2.start(); System.out.println(“End of main”); } } Determining When a Thread Ends

Output I from Thread X = 0 I from Thread X = 1 I from Thread X = 2 I from Thread X = 3 I from Thread X = 4 I from Thread X = 5 End of main

Output Square of 1 = 1 Square of 2 = 4 Square of 3 = 9 Square of 4 = 16 Square of 5 = 25 Cube of 1 = Cube of 2 = Cube of 3 = Cube of 4 = Cube of 5 = End of main

ECR

In the above example, thread is assigned with priority value 10, thread with 6 and threadA with 1 respectively. Synchronization When two or more threads need access to a shared resource, they need some way to ensure that the resource will be used by only one thread at a time. The process by which this is achieved is called synchronization. The most common reason for synchronization is when two or more threads need to access to a shared resource that can be used by only one thread at a time. For example, when a thread is writing to a file, the second thread must be prevented from doing so at the same time. Java provides unique, language-level support for it. Key to synchronization is the concept of the monitor (also called a semaphore ). A monitor is an object that is used as a mutually exclusive lock. Only one thread can own a monitor at a given time. When a thread acquires a lock, it is said to have entered the monitor. All other threads attempting to enter the locked monitor will be suspended until the first thread exits the monitor. These other threads are said to be waiting for the monitor. A thread that owns a monitor can reenter the same monitor if it so desires. There are two ways to synchronize a code.

  1. Using Synchronized Methods
  2. Using Synchronized Statement

Synchronized Methods We can make a method synchronized by prefixing the keyword synchronized. When a method is called, the calling thread enters the object’s monitor, which locks the object. While locked, no other object can enter the method. When the thread enters from the method, the monitor unlocks the object, allowing it to be used by another thread. //Use of Synchronize to control the access import java.io.*; class SumArray{ private int sum; synchronized int SumArray(int nums[]) { sum=0; for(int i=0; i<nums.length; i++) { sum+=nums[i]; System.out.println("Running total for" Thread.currentThread().getName() + "is " + sum); try{ Thread.sleep(100) } catch(InterruptedException e) { System.out.println("Thread Interrupted"); } } return (sum); } } class MyThread implements Runnable { Thread thrd; static SumArray sa = new SumArray(); int a[]; int answer; MyThread(String Name, int nums[]) { thrd=new Thread(this, Name); a=nums; thrd.start(); } public void run(){ int sum; System.out.println(thrd.getName() + "Starting"); answer=sa.SumArray(a); System.out.println("Sum for "+ thrd.getName() + answer); System.out.println(thrd.getName() + "Terminating"); } } class Sync {

ECR

public static void main(String args[]) { int a[]={1,2,3,4,5,6,7,8}; int b[]={1,3,5,7,9}; MyThread t1 = new MyThread3("Child #1", a); MyThread t2 = new MyThread3("Child #2", b); try { t1.thrd.join(); t2.thrd.join(); } catch(InterruptedException e) { System.out.println("Main Thread Interrupted !!"); } }}

The Synchronized Statement While creating synchronized methods within classes that is an easy and effective means of achieving synchronization, it will not work in all cases. For example, if we want to synchronize access to objects of a class that was not designed for multithreaded access that is, the class does not use synchronized methods. Further, this class was not created by us , but by a third party and we do not have access to the source code. Thus, we can’t add synchronized to the appropriate methods within the class. The solution to this problem is quite easy: We simply put calls to the methods defined by this class inside a synchronized block.

This is the general form of the synchronized statement: synchronized( object ) { // statements to be synchronized } Here, object is a reference to the object being synchronized. A synchronized block ensures that a call to a method that is a member of object occurs only after the current thread has successfully entered object ’s monitor.