File f = new File(\"C:/java/hello\"); InputStream f = new FileInputStream(f); Once you have InputStream object in hand, then there is a list of helper methods which can be used to read to stream or to do other operations on the stream. METHOD & DESCRIPTION 1. public void close() throws IOException{} This method closes the file output stream. Releases any system resources associated with the file. Throws an IOException. 2. protected void finalize()throws IOException {} This method cleans up the connection to the file. Ensures that the close method of this file output stream is called when there are no more references to this stream. Throws an IOException. 3. public int read(int r)throws IOException{} This method reads the specified byte of data from the InputStream. Returns an int. Returns the next byte of data and -1 will be returned if it's the end of the file. 4. public int read(byte[] r) throws IOException{} This method reads r.length bytes from the input stream into an array. Returns the total number of bytes read. If it is the end of the file, -1 will be returned. 5. public int available() throws IOException{} Gives the number of bytes that can be read from this file input stream. Returns an int There are other important input streams available, for more detail you can refer to the following links − ByteArrayInputStream DataInputStream FILEOUTPUTSTREAM FileOutputStream is used to create a file and write data into it. The stream would create a file, if it doesn't already exist, before opening it for output. Here are two constructors which can be used to create a FileOutputStream object. Following constructor takes a file name as a string to create an input stream object to write the file OutputStream f = new FileOutputStream(\"C:/java/hello\") CU IDOL SELF LEARNING MATERIAL (SLM) 151
Following constructor takes a file object to create an output stream object to write the file. First, we create a file object using File() method as follows − File f = new File(\"C:/java/hello\"); OutputStream f = new FileOutputStream(f); Once you have OutputStream object in hand, then there is a list of helper methods, which can be used to write to stream or to do other operations on the stream. Method & Description 1. public void close() throws IOException{} This method closes the file output stream. Releases any system resources associated with the file. Throws an IOException. 2. protected void finalize()throws IOException {} This method cleans up the connection to the file. Ensures that the close method of this file output stream is called when there are no more references to this stream. Throws an IOException. 3. public void write(int w)throws IOException{} This methods writes the specified byte to the output stream. 4. public void write(byte[] w) Writes w length bytes from the mentioned byte array to the OutputStream There are other important output streams available, for more detail you can refer to the following links ByteArrayOutputStream DataOutputStream Example Following is the example to demonstrate InputStream and OutputStream − import java.io.*; public class fileStreamTest { public static void main(String args[]) { try { byte bWrite [] = {11,21,3,40,5}; OutputStream os = new FileOutputStream(\"test.txt\"); for(int x = 0; x < bWrite.length ; x++) { CU IDOL SELF LEARNING MATERIAL (SLM) 152
os.write( bWrite[x] ); // writes the bytes } os.close(); InputStream is = new FileInputStream(\"test.txt\"); int size = is.available(); for(int i = 0; i < size; i++) { System.out.print((char)is.read() + \" \"); } is.close(); } catch (IOException e) { System.out.print(\"Exception\"); } } The above code would create file test.txt and would write given numbers in binary format. Same would be the output on the stdout screen. The above code would create file test.txt and would write given numbers in binary format. Same would be the output on the stdout screen. CU IDOL SELF LEARNING MATERIAL (SLM) 153
FILE NAVIGATION AND I/O There are several other classes that we would be going through to get to know the basics of File Navigation and I/O. File Class FileReader Class FileWriter Class DIRECTORIES IN JAVA A directory is a File which can contain a list of other files and directories. You use File object to create directories, to list down files available in a directory. For complete detail, check a list of all the methods which you can call on File object and what are related to directories. Creating Directories There are two useful File utility methods, which can be used to create directories − The mkdir( ) method creates a directory, returning true on success and false on failure. Failure indicates that the path specified in the File object already exists, or that the directory cannot be created because the entire path does not exist yet. The mkdirs() method creates both a directory and all the parents of the directory. Following example creates \"/tmp/user/java/bin\" directory − Example import java.io.File; public class CreateDir { public static void main(String args[]) { String dirname = \"/tmp/user/java/bin\"; File d = new File(dirname); // Create directory now. d.mkdirs(); } } Compile and execute the above code to create \"/tmp/user/java/bin\". CU IDOL SELF LEARNING MATERIAL (SLM) 154
Note − Java automatically takes care of path separators on UNIX and Windows as per conventions. If you use a forward slash (/) on a Windows version of Java, the path will still resolve correctly. Listing Directories You can use list( ) method provided by File object to list down all the files and directories available in a directory as follows − Example import java.io.File; public class ReadDir { public static void main(String[] args) { File file = null; String[] paths; try { // create new file object file = new File(\"/tmp\"); // array of files and directory paths = file.list(); // for each name in the path array for(String path:paths) { // prints filename and directory name System.out.println(path); } } catch (Exception e) { // if any error occurs e.printStackTrace(); } } } This will produce the following result based on the directories and files available in your /tmp directory − CU IDOL SELF LEARNING MATERIAL (SLM) 155
Output test1.txt test2.txt ReadDir.java ReadDir.class 4.9 SUMMARY Inheritance is one of the cornerstones of object-oriented programming because it allows the creation of hierarchical classifications. Using inheritance, you can create a general class that defines traits common to a set of related items. Using the keyword interface, you can fully abstract a class’ interface from its imple- mutation. That is, using interface, you can specify what a class must do, but not how it does it. Interfaces are syntactically similar to classes, but they lack instance variables, and their methods are declared without any body. To implement an interface, a class must create the complete set of methods defined by the interface. However, each class is free to determine the details of its own implementation. By providing the interface keyword, Java allows you to fully utilize the “one interface, multiple methods” aspect of polymorphism. There are situations in which you will want to define a superclass that declares the structure of a given abstraction without providing a complete implementation of every method. That is, sometimes you will want to create a superclass that only defines a generalized form that will be shared by all of its subclasses, leaving it to each subclass to fill in the details. Such a class determines the nature of the methods that the subclasses must implement. To create a package is quite easy: simply include a package command as the first statement in a Java source file. Any classes declared within that file will belong to the specified package. The package statement defines a name space in which classes are stored. A directory is a File which can contain a list of other files and directories. You use File object to create directories, to list down files available in a directory. For complete detail, check a list of all the methods which you can call on File object and what are related to directories. The unique name had to be used for each class to avoid name collisions. After a while, without some way to manage the name space, you could run out of convenient, descriptive names for individual classes. You also need some way to be assured that CU IDOL SELF LEARNING MATERIAL (SLM) 156
the name you choose for a class will be reasonably unique and not collide with class names chosen by other programmers. (Imagine a small group of programmers fighting over who gets to use the name “Foobar” as a class name. Or, imagine the entire Internet community arguing over who first named a class “Espresso.”) Thankfully, Java provides a mechanism for partitioning the class name space into more manageable chunks. This mechanism is the package. The package is both a naming and a visibility control mechanism. You can define classes inside a package that are not accessible by code outside that package. You can also define class members that are only exposed to other members of the same package. This allows your classes to have intimate knowledge of each other, but not expose that knowledge to the rest of the world. 4.10 KEYWORDS Inheritance: Inheritance in Java is a concept that acquires the properties from one class to other classes; for example, the relationship between father and son. In Java, a class can inherit attributes and methods from another class. The class that inherits the properties is known as the sub-class or the child class. Interface: An interface is declared by using the interface keyword. It provides total abstraction; means all the methods in an interface are declared with the empty body, and all the fields are public, static and final by default. A class that implements an interface must implement all the methods declared in the interface. Abstract: abstract is a non-access modifier in java applicable for classes, methods but not variables. It is used to achieve abstraction which is one of the pillars of Object Oriented Programming (OOP). Following are different contexts where abstract can be used in Java. Package: A package is a namespace that organizes a set of related classes and interfaces. ... Because software written in the Java programming language can be composed of hundreds or thousands of individual classes, it makes sense to keep things organized by placing related classes and interfaces into packages. Stream: A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result. The features of Java stream are a stream is not a data structure instead it takes input from the Collections, Arrays or I/O channels. 4.11 LEARNING ACTIVITY 1. Discuss the topic inheritance. CU IDOL SELF LEARNING MATERIAL (SLM) 157
________________________________________________________________________ __________________________________________________________________ 2. Conduct a seminar on I/O stream classes ________________________________________________________________________ __________________________________________________________________ 4.12 UNIT END QUESTIONS A. Descriptive Questions Short Questions: 1. What is inheritance? 2. What is interface? 3. What is abstract class? 4. What are packages? 5. What are I/O stream classes? Long Questions: 1. What is inheritance explain in detail? 2. Explain inheritance in detail? 3. What are packages explain in detail? 4. What is I/O stream classes explain in detail? 5. What is abstract class explain in detail? B. Multiple Choice Questions 1. Which of this keyword must be used to inherit a class? a. Super b. This c. Extent d. Extends 2. What is a class member declared protected becomes a member of subclass of which type? a. Public member b. Private member c. Protected member CU IDOL SELF LEARNING MATERIAL (SLM) 158
d. Static member 3. What is an interface in Java is like a 100%? a. Abstract class b. Public class c. Inner class d. Anonymous class 4. What does Java Class inherits constants and methods of an interface using keyword? a. INTERFACE b. IMPLEMENTS c. EXTENDS d. All the these 5. Which of these keywords is used to define packages in Java? a. pkg b. Pkg c. package d. Package Answers 1-d, 2-b, 3-a, 4-b, 5-c. 4.17 REFERENCES References Powell, Thomas A, and Schneider, Fritz, 2012. JavaScript: The Complete Reference, Third Edition. McGraw-Hill. Chapter 11 Crockford, Douglas, 2008. JavaScript: The Good Parts. Patrick Naughton, Herbert Schildt. Java 2: The Complete Reference, third edition. Textbooks Goodman, Danny, with Morrison, Michael, 2004. JavaScript Bible, 5th Edition. Wiley Publishing, Inc., Indianapolis, USA. Chapter 33, Functions and Custom Objects, p 987. CU IDOL SELF LEARNING MATERIAL (SLM) 159
Gosling, James; Joy, Bill; Steele, Guy; Bracha, Gillad (2005). Java Language Specification 3rd ed. Powell, Thomas A, and Schneider, Fritz, 2012. Website https://www.mygreatlearning.com https://www.w3schools.com https://beginnersbook.com CU IDOL SELF LEARNING MATERIAL (SLM) 160
UNIT –5:WRAPPER CLASS 2 STRUCTURE 5.0 Learning Objectives 5.1 Introduction 5.2Text Streams 5.3 Serialization 5.3.1Serializable 5.3.2Externalizable 5.3.3ObjectOutput 5.3.4ObjectOutputStream 5.3.5 ObjectInput 5.3.6 ObjectInputStream 5.3.7 A Serialization Example 5.4Print Stream 5.5Buffered Stream 5.5.1 BufferedInputStream 5.5.2 BufferedOutputStream 5.5.3 PushbackInputStream 5.6 Random Access File 5.7Summary 5.8 Keywords 5.9Learning Activity 5.10Unit End Questions 5.11 References 5.0 LEARNING OBJECTIVES After studying this unit, you will be able to: Explain the text streams and serialization Illustrate the print stream CU IDOL SELF LEARNING MATERIAL (SLM) 161
Explain the buffered stream Describe the random access file 5.1 INTRODUCTION This chapter explores java.io, which provides support for I/O operations. we presented an overview of Java’s I/O system. Here, we will examine the Java I/O system in greater detail. As all programmers learn early on, most programs cannot accomplish their goals without accessing external data. Data is retrieved from an input source. The results of a program are sent to an output destination. In Java, these sources or destinations are defined very broadly. For example, a network connection, memory buffer, or disk file can be manipulated by the Java I/O classes. Although physically different, these devices are all handled by the same abstraction: the stream. A stream is a logical entity that either produces or consumes information. A stream is linked to a physical device by the Java I/O system. All streams behave in the same manner, even if the actual physical devices they are linked to differ. 5.2 TEXT STREAMS A stream can be considered as a sequence of bytes travelling from a source to a destination. All input and output data transfer in Java happens through streams. There can be different types of sources and destinations such as disk files, input devices like keyboards and even other programs, and there are different stream classes available corresponding to each of these types of sources and destinations. Classification of streams Input and output streams Based on the direction of data flow, streams can be categorized as input streams and output streams. Byte and character streams Based on the type of data we can classify streams as byte streams and text streams BYTE STREAMS o Represent data in the form of bytes. o All byte stream classes are descended from InputStream and OutputStream. o Class names of byte streams end with the word stream as in FileInputStream and FileOutputStream. Text streams CU IDOL SELF LEARNING MATERIAL (SLM) 162
o Represent data as characters. o All character stream classes are descended from Reader and Writer. o Class names of text streams end with the word ‘Reader’ or ‘Writer’ as in FileReader and FileWriter. o Java stores character values using Unicode conventions. Text streams automatically convert the Unicode internal format to and from the local character set. WRAPPER STREAMS One stream may wrap around another stream to add some functionality to the inner stream or to make the inner stream do some low level tasks. Filter streams wrap around other streams and transform the data providing additional functionality. Subclasses of FilterInputStream are BufferedInputStream, CheckedInputStream, CipherInputStream, DataInputStream, DeflaterInputStream, DigestInputStream, InflaterInputStream, LineNumberInputStream, ProgressMonitorInputStream and PushbackInputStream. Subclasses of FilterOutputStream are BufferedOutputStream, CheckedOutputStream, CipherOutputStream, DataOutputStream, DeflaterOutputStream, DigestOutputStream and InflaterOutputStream. To improve efficiency we can use Buffered classes in connection with other streams BufferedOutputStream can be used along with FileOutputStream to write data to a file. The characters will not be directly written to the file, but to the buffer. When the buffer is full, then the FileOutputStream will write the entire buffer in a single step into the file. Similarly we can use BufferedInputStream to read a buffer full of data at a time from the file. Another example is DataInputStream; we can attach the keyboard to a data input stream as: DataInputStream dis=new DataInputStream(System.in);. Stream variables in System class java.lang.System class’s static member variable ‘in’ is of type PrintStream and represents the standard input device that is keyboard by default. CU IDOL SELF LEARNING MATERIAL (SLM) 163
System.out of type PrintStream and System.err of type InputStream, both are used to display messages on the default output device, which is monitor. System. Out is used to display normal messages whereas System.err is used to display error messages. Text streams as wrappers for byte streams Text streams often act as wrappers for byte streams; the byte streams perform the low level physical IO operations, and text streams handle the translation between characters and bytes. Many readers cannot wrap around a byte stream. InputStreamReader can be useful in such cases as it can accept byte streams and act as a bridge between character streams and byte streams. Example: BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); System.out.println(“Enter the filename”); String fname=br.readLine(); This code will print \"Enter the filename\" to the console and then read a line from the console. MARKABLE STREAMS Mark able streams provide the capability to mark a position in the stream and then later reset the stream so that it can be reread from the marked position. The markSupported() method returns true if the stream is mark able. The mark() method marks a position in the stream and it takes the buffer capacity as an integer parameter. o The buffer memory is used to keep track of the data between the mark and the current position and when this buffer memory is exceeded, the mark becomes invalid. The reset() method simply repositions the stream to its last marked position. 5.3 SERIALIZATION Serialization is the process of writing the state of an object to a byte stream. This is useful when you want to save the state of your program to a persistent storage area, such as a file. At a later time, you may restore these objects by using the process of deserialization. Serialization is also needed to implement Remote Method Invocation (RMI). RMI allows a Java object on one machine to invoke a method of a Java object on a different machine. An CU IDOL SELF LEARNING MATERIAL (SLM) 164
object may be supplied as an argument to that remote method. The sending machine serializes the object and transmits it. The receiving machine desterilizes it. Assume that an object to be serialized has references to other objects, which, in turn, have references to still more objects. This set of objects and the relationships among them form a directed graph. There may also be circular references within this object graph. That is, object X may contain a reference to object Y, and object Y may contain a reference back to object X. Objects may also contain references to themselves. The object serialization and deserialization facilities have been designed to work correctly in these scenarios. If you attempt to serialize an object at the top of an object graph, all of the other referenced objects are recursively located and serialized. Similarly, during the process of deserialization, all of these objects and their references are correctly restored. An overview of the interfaces and classes that support serialization follows. 5.3.1 Serializable Only an object that implements the Serializable interface can be saved and restored by the serialization facilities. The Serializable interface defines no members. It is simply used to indicate that a class may be serialized. If a class is serializable, all of its subclasses are also serializable. Variables that are declared as transient are not saved by the serialization facilities. Also, static variables are not saved. 5.3.2 Externalizable The Java facilities for serialization and deserialization have been designed so that much of the work to save and restore the state of an object occurs automatically. However, there are cases in which the programmer may need to have control over these processes. For example, it may be desirable to use compression or encryption techniques. The Externalizable interface is designed for these situations. The Externalizable interface defines these two methods: void readExternal(ObjectInput inStream) throws IOException, ClassNotFoundException void writeExternal(ObjectOutput outStream) throws IOException In these methods, inStream is the byte stream from which the object is to be read, and outStream is the byte stream to which the object is to be written. 5.3.3 Object Output The ObjectOutput interface extends the DataOutput interface and supports object serialization. It defines the methods shown in table. Note especially the writeObject( ) CU IDOL SELF LEARNING MATERIAL (SLM) 165
method. This is called to serialize an object. All of these methods will throw an IOException on error conditions. Method Description void close( ) Closes the invoking stream. Further write Attempts will generate an IOException. void flush( ) Finalizes the output state so that any Buffers are cleared. That is, it flushes the Output buffers. void write(byte buffer[ ]) Writes an array of bytes to the invoking Stream. void write(byte buffer[ ], int offset, Writes a subrange of numBytes bytes from int numBytes) the array buffer, beginning at buffer[offset]. void write(int b) Writes a single byte to the invoking stream. The byte written is the low-order byte of b. void writeObject(Object obj) Writes object obj to the invoking stream. 5.3.4 Object Output Stream The ObjectOutputStream class extends the OutputStream class and implements the ObjectOutput interface. It is responsible for writing objects to a stream. A constructor of this class is ObjectOutputStream(OutputStream outStream) throws IOException The argument outStream is the output stream to which serialized objects will be written. The most commonly used methods in this class are shown in table. They will throw an IOException on error conditions. Java 2 added an inner class to ObjectOuputStream called PutField. It facilitates the writing of persistent fields and its use is beyond the scope of this book. Method Description void close( ) Closes the invoking stream. Further write Attempts will generate an IOException. CU IDOL SELF LEARNING MATERIAL (SLM) 166
void flush( ) Finalizes the output state so that any Buffers are cleared. That is, it flushes the void write(byte buffer[ ]) Output buffers. Writes an array of bytes to the invoking void write(byte buffer[ ], int offset, Stream. int numBytes) Writes a sub range of numBytes from void write(int b) The array buffer, beginning at buffer [offset]. void writeBoolean(Boolean b) Writes a single byte to the invoking stream. void writeByte The byte written is the low-order byte of b. Writes a Boolean to the invoking stream. void writeBytes Writes a byte to the invoking stream. The byte written is the low-order byte of b. void writeChar(int c) Writes the bytes representing str to the void writeChars(String str) Invoking stream. Writes a char to the invoking stream. void writeDouble(double d) Writes the characters in str to the invoking void writeFloat(float f ) Stream. void writeInt(int i) Writes a double to the invoking stream. void writeLong(long l) Writes a float to the invoking stream. final void writeObject(Object obj) Writes an int to the invoking stream. void writeShort(int i) Writes a long to the invoking stream. Writes obj to the invoking stream. Writes a short to the invoking stream. CU IDOL SELF LEARNING MATERIAL (SLM) 167
5.3.5 Object Input The ObjectInput interface extends the DataInput interface and defines the methods shown in Table. It supports object serialization. Note especially the readObject( ) method. This is called to desterilize an object. All of these methods will throw an IOException on error conditions. Method Description int available( ) Returns the number of bytes that are now Available in the input buffer. void close( ) Closes the invoking stream. Further read Attempts will generate an IOException. int read( ) Returns an integer representation of the next Available byte of input. –1 is returned when The end of the file is encountered. int read(byte buffer[ ]) Attempts to read up to buffer. Length bytes into buffer, returning the number of bytes that Were successfully read. –1 is returned when The end of the file is encountered. int read(byte buffer[ ], int offset, Attempts to read up to numBytes into int numBytes) buffer starting at buffer[offset], returning the Number of bytes that were successfully read. Object readObject( ) –1 is returned when the end of the file is Encountered. Reads an object from the invoking stream. CU IDOL SELF LEARNING MATERIAL (SLM) 168
long skip(long numBytes) Ignores (that is, skips) num Bytes in the invoking stream, returning the number of bytes actually ignored. 5.3.6 Object Input Stream The ObjectInputStream class extends the InputStream class and implements the ObjectInput interface. ObjectInputStream is responsible for reading objects from a stream. A constructor of this class is ObjectInputStream(InputStream inStream) throws IOException, StreamCorruptedException The argument inStream is the input stream from which serialized objects should be read. The most commonly used methods in this class are shown in Table. They will throw an IOException on error conditions. Java 2 added an inner class to ObjectInputStream called GetField. It facilitates the reading of persistent fields and its use is beyond the scope of this book. Also, the method readLine( ) was deprecated by Java 2 and should no longer be used. Method Description int available( ) Returns the number of bytes that are now available in the input buffer. void close( ) Closes the invoking stream. Further read attempts will generate an IOException. int read( ) Returns an integer representation of the next available byte of input. –1 is returned when the end of the file is encountered. int read(byte buffer[ ], int offset, Attempts to read up to numBytes bytes into int numBytes) buffer starting at buffer[offset], returning the number of bytes successfully read. –1 is returned when the end of the file is CU IDOL SELF LEARNING MATERIAL (SLM) 169
encountered. boolean readBoolean( ) Reads and returns a boolean from the invoking stream. byte readByte( ) Reads and returns a byte from the invoking stream. char readChar( ) Reads and returns a char from the invoking stream. double readDouble( ) double readDouble( ) float readFloat( ) Reads and returns a float from the invoking stream. void readFully(byte buffer[ ]) Reads numBytes bytes into buffer starting at buffer[offset]. Returns only when numBytes have been read. int readInt( ) Reads and returns an int from the invoking stream. long readLong( ) Reads and returns a long from the invoking stream. final Object readObject( ) Reads and returns an object from the invoking stream. 5.3.7 A Serialization Example The following program illustrates how to use object serialization and deserialization. It begins by instantiating an object of class MyClass. This object has three instance variables that are of types String, int, and double. This is the information we want to save and restore. A FileOutputStream is created that refers to a file named “serial,” and an ObjectOutputStream is created for that file stream. The writeObject( ) method of ObjectOutputStream is then used to serialize our object. The object output stream is flushed and closed. A FileInputStream is then created that refers to the file named “serial,” and an ObjectInputStream is created for that file stream. The readObject( ) method of ObjectInputStream is then used to deserialize our object. The object input stream is then CU IDOL SELF LEARNING MATERIAL (SLM) 170
closed. Note that MyClass is defined to implement the Serializable interface. If this is not done, a NotSerializableException is thrown. Try experimenting with this program by declaring some of the MyClass instance variables to be transient. That data is then not saved during serialization. import java.io.*; public class SerializationDemo { public static void main(String args[]) { // Object serialization try { MyClass object1 = new MyClass(\"Hello\", -7, 2.7e10); System.out.println(\"object1: \" + object1); FileOutputStream fos = new FileOutputStream(\"serial\"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(object1); oos.flush(); oos.close(); } catch(Exception e) { System.out.println(\"Exception during serialization: \" + e); System.exit(0); } // Object deserialization try { MyClass object2; FileInputStream fis = new FileInputStream(\"serial\"); ObjectInputStream ois = new ObjectInputStream(fis); object2 = (MyClass)ois.readObject(); ois.close(); System.out.println(\"object2: \" + object2); } CU IDOL SELF LEARNING MATERIAL (SLM) 171
catch(Exception e) { System.out.println(\"Exception during deserialization: \" + e); System.exit(0); } } } class MyClass implements Serializable { String s; int i; double d; public MyClass(String s, int i, double d) { this.s = s; this.i = i; this.d = d; } public String toString() { return \"s=\" + s + \"; i=\" + i + \"; d=\" + d; } } This program demonstrates that the instance variables of object1 and object2 are identical. The output is shown here: object1: s=Hello; i=-7; d=2.7E10 object2: s=Hello; i=-7; d=2.7E10 5.4 PRINT STREAM The PrintStream class provides all of the formatting capabilities we have been using from the System file handle, System.out, since the beginning of the book. Here are two of its constructors: PrintStream(OutputStream outputStream) PrintStream(OutputStream output Stream, boolean flushOnNewline) CU IDOL SELF LEARNING MATERIAL (SLM) 172
where flushOnNewline controls whether Java flushes the output stream every time a newline (\\n) character is output. If flushOnNewline is true, flushing automatically takes place. If it is false, flushing is not automatic. The first constructor does not automatically flush. Java’s PrintStream objects support the print( ) and println( ) methods for all types, including Object. If an argument is not a simple type, the PrintStream methods will call the object’s toString( ) method and then print the result. 5.5 BUFFERED STREAM BufferedReader improves performance by buffering input. It has two constructors: BufferedReader(Reader inputStream) BufferedReader(Reader inputStream, int bufSize) The first form creates a buffered character stream using a default buffer size. In the second, the size of the buffer is passed in bufSize. As is the case with the byte-oriented stream, buffering an input character stream also provides the foundation required to support moving backward in the stream within the available buffer. To support this, BufferedReader implements the mark( ) and reset( ) methods, and BufferedReader.markSupported( ) returns true. The following example reworks the BufferedInputStream example, shown earlier, so that it uses a BufferedReader character stream rather than a buffered byte stream. As before, it uses mark( ) and reset( ) methods to parse a stream for the HTML entity reference for the copyright symbol. Such a reference begins with an ampersand (&) and ends with a semicolon (;) without any intervening whitespace. The sample input has two ampersands, to show the case where the reset( ) happens and where it does not. Output is the same as that shown earlier. // Use buffered input. import java.io.*; class BufferedReaderDemo { public static void main(String args[]) throws IOException { String s = \"This is a © copyright symbol \" + \"but this is © not.\\n\"; char buf[] = new char[s.length()]; s.getChars(0, s.length(), buf, 0); CharArrayReader in = new CharArrayReader(buf); BufferedReader f = new BufferedReader(in); CU IDOL SELF LEARNING MATERIAL (SLM) 173
int c; boolean marked = false; while ((c = f.read()) != -1) { switch(c) { case '&': if (!marked) { f.mark(32); marked = true; } else { marked = false; } break; case ';': if (marked) { marked = false; System.out.print(\"(c)\"); } else System.out.print((char) c); break; case ' ': if (marked) { marked = false; f.reset(); System.out.print(\"&\"); } else System.out.print((char) c); break; default: if (!marked) CU IDOL SELF LEARNING MATERIAL (SLM) 174
System.out.print((char) c); break; } } } } 5.5.1 Buffered Input Stream Buffering I/O is a very common performance optimization. Java’s BufferedInputStream class allows you to “wrap” any InputStream into a buffered stream and achieve this performance improvement. BufferedInputStream has two constructors: BufferedInputStream(InputStream inputStream) BufferedInputStream(InputStream inputStream, int bufSize) The first form creates a buffered stream using a default buffer size. In the second, the size of the buffer is passed in buff size. Use of sizes that are multiples of memory pages, disk block, and so on can have a significant positive impact on performance. This is, however, implementation-dependent. An optimal buffer size is generally dependent on the host operating system, the amount of memory available, and how the machine is configured. To make good use of buffering doesn’t necessarily require quite this degree of sophistication. A good guess for a size is around 8,192 bytes, and attaching even a rather small buffer to an I/O stream is always a good idea. That way, the low-level system can read blocks of data from the disk or network and store the results in your buffer. Thus, even if you are reading the data a byte at a time out of the InputStream, you will be manipulating fast memory over 99.9 percent of the time. kward in the stream of the available buffer. Beyond the read( ) and skip( ) methods implemented in any InputStream, BufferedInputStream also supports the mark( ) and reset( ) methods. This support is reflected by BufferedInputStream.markSupported( ) returning true. The following example contrives a situation where we can use mark( ) to remember where we are in an input stream and later use reset( ) to get back there. This example is parsing a stream for the HTML entity reference for the copyright symbol. Such a reference begins with an ampersand (&) and ends with a semicolon (;) without any intervening whitespace. The sample input has two ampersands to show the case where the reset( ) happens and where it does not. // Use buffered input. CU IDOL SELF LEARNING MATERIAL (SLM) 175
import java.io.*; class BufferedInputStreamDemo { public static void main(String args[]) throws IOException { String s = \"This is a © copyright symbol \" + \"but this is © not.\\n\"; byte buf[] = s.getBytes(); ByteArrayInputStream in = new ByteArrayInputStream(buf); BufferedInputStream f = new BufferedInputStream(in); int c; boolean marked = false; while ((c = f.read()) != -1) { switch(c) { case '&': if (!marked) { f.mark(32); marked = true; } else { marked = false; } break; case ';': if (marked) { marked = false; System.out.print(\"(c)\"); } else System.out.print((char) c); break; case ' ': if (marked) { CU IDOL SELF LEARNING MATERIAL (SLM) 176
marked = false; f.reset(); System.out.print(\"&\"); } else System.out.print((char) c); break; default: if (!marked) System.out.print((char) c); break; } } } } Notice that this example uses mark(32), which preserves the mark for the next 32 bytes read (which is enough for all entity references). Here is the output produced by this program: This is a (c) copyright symbol but this is © not. Use of mark( ) is restricted to access within the buffer. This means that you can only specify a parameter to mark( ) that is smaller than the buffer size of the stream. 5.5.2 Buffered Output Stream A BufferedOutputStream is similar to any OutputStream with the exception of an added flush( ) method that is used to ensure that data buffers are physically written to the actual output device. Since the point of a BufferedOutputStream is to improve performance by reducing the number of times the system actually writes data, you may need to call flush( ) to cause any data that is in the buffer to get written. Unlike buffered input, buffering output does not provide additional functionality. Buffers for output in Java are there to increase performance. Here are the two available constructors: BufferedOutputStream(OutputStream outputStream) BufferedOutputStream(OutputStream outputStream, int bufSize) CU IDOL SELF LEARNING MATERIAL (SLM) 177
The first form creates a buffered stream using a buffer of 512 bytes. In the second form, the size of the buffer is passed in bufSize. 5.5.3 Pushback Input Stream One of the novel uses of buffering is the implementation of pushback. Pushback is used on an input stream to allow a byte to be read and then returned (that is, “pushed back”) to the stream. The PushbackInputStream class implements this idea. It provides a mechanism to “peek” at what is coming from an input stream without disrupting it. PushbackInputStream has the following constructors: PushbackInputStream(InputStream inputStream) PushbackInputStream(InputStream inputStream, int numBytes) The first form creates a stream object that allows one byte to be returned to the input stream. The second form creates a stream that has a pushback buffer that is numBytes long. This allows multiple bytes to be returned to the input stream. Beyond the familiar methods of InputStream, PushbackInputStream provides unread( ), shown here: void unread(int ch) void unread(byte buffer[ ]) void unread(byte buffer, int offset, int numChars) The first form pushes back the low-order byte of ch. This will be the next byte returned by a subsequent call to read( ). The second form returns the bytes in buffer. The third form pushes back numChars bytes beginning at offset from buffer. An IOException will be thrown if there is an attempt to return a byte when the pushback buffer is full. Java 2 made a small change to PushbackInputStream: it added the skip( ) method. Here is an example that shows how a programming language parser might use a PushbackInputStream and unread( ) to deal with the difference between the = = operator for comparison and the = operator for assignment: // Demonstrate unread(). import java.io.*; class PushbackInputStreamDemo { public static void main(String args[]) throws IOException { String s = \"if (a == 4) a = 0;\\n\"; byte buf[] = s.getBytes(); ByteArrayInputStream in = new ByteArrayInputStream(buf); PushbackInputStream f = new PushbackInputStream(in); int c; CU IDOL SELF LEARNING MATERIAL (SLM) 178
while ((c = f.read()) != -1) { switch(c) { case '=': if ((c = f.read()) == '=') System.out.print(\".eq.\"); else { System.out.print(\"<-\"); f.unread(c); } break; default: System.out.print((char) c); break; } } } } Here is the output for this example. Notice that = = was replaced by “.eq.” and = was replaced by “<–”. if (a .eq. 4) a <- 0; PushbackInputStream has the side effect of invalidating the mark( ) or reset( ) methods of the InputStream used to create it. Use markSupported( ) to check any stream on which you are going to use mark( )/reset( ). 5.6 RANDOM ACCESS FILE RandomAccessFile encapsulates a random-access file. It is not derived from InputStream or OutputStream. Instead, it implements the interfaces DataInput and DataOutput, which define the basic I/O methods. It also supports positioning requests—that is, you can position the file pointer within the file. It has these two constructors: RandomAccessFile(File fileObj, String access) throws FileNotFoundException RandomAccessFile(String filename, String access) CU IDOL SELF LEARNING MATERIAL (SLM) 179
throws FileNotFoundException In the first form, fileObj specifies the name of the file to open as a File object. In the second form, the name of the file is passed in filename. In both cases, access determines what type of file access is permitted. If it is “r”, then the file can be read, but not written. If it is “rw”, then the file is opened in read-write mode. If it is “rws”, the file is opened for read-write operations and every change to the file’s data or metadata will be immediately written to the physical device. If it is “rwd”, the file is opened for read-write operations and every change to the file’s data will be immediately written to the physical device. The method seek( ), shown here, is used to set the current position of the file pointer within the file: void seek(long newPos) throws IOException Here, newPos specifies the new position, in bytes, of the file pointer from the beginning of the file. After a call to seek( ), the next read or write operation will occur at the new file position. RandomAccessFile implements the standard input and output methods, which you can use to read and write to random access files. It also includes some additional methods. One is setLength( ). It has this signature: void setLength(long len) throws IOException This method sets the length of the invoking file to that specified by len. This method can be used to lengthen or shorten a file. If the file is lengthened, the added portion is undefined. Java 2, version 1.4 added the getChannel( ) method to RandomAccessFile. This method returns a channel connected to the RandomAccessFile object. Channels are used by the new I/O classes contained in java.nio. 5.7SUMMARY A stream can be considered as a sequence of bytes travelling from a source to a destination. All input and output data transfer in Java happens through streams. Serialization is the process of writing the state of an object to a byte stream. This is useful when you want to save the state of your program to a persistent storage area, such as a file. At a later time, you may restore these objects by using the process of deserialization. The Java facilities for serialization and deserialization have been designed so that much of the work to save and restore the state of an object occurs automatically. However, there are cases in which the programmer may need to have control over these processes. The PrintStream class provides all of the formatting capabilities we have been using from the System file handle, System.out, since the beginning of the book. Here are two of its constructors: CU IDOL SELF LEARNING MATERIAL (SLM) 180
RandomAccessFile encapsulates a random-access file. It is not derived from InputStream or OutputStream. Instead, it implements the interfaces DataInput and DataOutput, which define the basic I/O methods. RandomAccessFile implements the standard input and output methods, which you can use to read and write to random access files. It also includes some additional methods. One is setLength( ). It has this signature: void setLength(long len) throws IOException This method sets the length of the invoking file to that specified by len. This method can be used to lengthen or shorten a file. If the file is lengthened, the added portion is undefined. Java 2, version 1.4 added the getChannel( ) method to RandomAccessFile. This method returns a channel connected to the RandomAccessFile object. Channels are used by the new I/O classes contained in java.nio. The PrintStream class provides all of the formatting capabilities we have been using from the System file handle, System.out, since the beginning of the book. Here are two of its constructors: 5.8 KEYWORDS I/O Stream: A stream is a method to sequentially access a file. I/O Stream means an input source or output destination representing different types of sources e.g. disk files. The java.io package provides classes that allow you to convert between Unicode character streams and byte streams of non-Unicode text. Serialization: To serialize an object means to convert its state to a byte stream so that the byte stream can be reverted back into a copy of the object. A Java object is serializable if its class or any of its superclasses implements either the java. Button class implements the Serializable interface, so you can serialize a java. Serializable:To serialize an object means to convert its state to a byte stream so that the byte stream can be reverted back into a copy of the object. A Java object is serializable if its class or any of its superclasses implements either the java. Externalizable: Externalizable is an interface that enables you to define custom rules and your own mechanism for serialization. ... Thus externalization comes to give the programmers full control in reading and writing objects during serialization . As name suggests it is externalizing your serialization. PrintStream: A PrintStream adds functionality to another output stream, namely the ability to print representations of various data values conveniently. Unlike other output streams, a PrintStream never throws an IOException ; instead, exceptional situations merely set an internal flag that can be tested via the checkError method. CU IDOL SELF LEARNING MATERIAL (SLM) 181
5.9 LEARNING ACTIVITY 1. Discuss the topic serialization. ________________________________________________________________________ __________________________________________________________________ 2. Conduct a seminar on buffered stream ________________________________________________________________________ __________________________________________________________________ 5.10 UNIT END QUESTIONS A. Descriptive Questions Short Questions: 1. What are text streams? 2. What is serialization? 3. What is serializable? 4. What is print stream? 5. What is buffered stream? Long Questions: 1. What is serialization explain in detail? 2. What is print stream explain in detail? 3. What is buffered stream explain in detail? 4. What is random access file explain in detail? 5. Explain buffered input and output stream in detail? B. Multiple Choice Questions 1. Which of these is a process of writing the state of an object to a byte stream? a. Serialization b. Externalization c. File Filtering d. All of these 2. Which of this process occur automatically by java run time system? a. Garbage collection CU IDOL SELF LEARNING MATERIAL (SLM) 182
b. Serialization c. File Filtering d. All of these 3. Which of this class is implemented by FilterInputStream class? a. InputStream b. BufferedInputStream c. FileInputStream d. BufferedFileInputStream 4. Which of these class contains the methods print() & println()? a. System b. System.out c. BufferedOutputStream d. PrintStream 5. Which of these method of class StringBuffer is used to reverse sequence of characters? a. Reverse() b. Reverseall() c. Reverse() d. ReverseAll() Answers 1-a, 2-a, 3-c, 4-d, 5-a. 5.11 REFERENCES References Byous, Jon (c. 1998). \"Java technology: The early years\". Sun Developer Network. Sun Microsystems. Archived from the original on April 20, 2005. Retrieved April 22, 2005. Chander, Sharat. \"Introducing Java SE 11\". oracle.com. Archived from the original on September 26, 2018. Retrieved September 26, 2018. Patrick Naughton, Herbert Schildt. Java 2: The Complete Reference, third edition. CU IDOL SELF LEARNING MATERIAL (SLM) 183
Textbooks Arnold, Ken. \"Generics Considered Harmful\". java.net. Archived from the original on October 10, 2007. Retrieved September 10, 2015. Gosling, James; Joy, Bill; Steele, Guy; Bracha, Gillad (2005). Java Language Specification 3rd Ed. Powell, Thomas A, and Schneider, Fritz, 2012. Website https://www.mygreatlearning.com https://www.w3schools.com https://beginnersbook.com CU IDOL SELF LEARNING MATERIAL (SLM) 184
UNIT – 6:MULTITHREADING STRUCTURE 6.0 Learning Objectives 6.1 Introduction 6.2 The Main Thread 6.3 Java Thread Model 6.4 Thread Priorities 6.5 Synchronization in Java 6.6 Inter-thread Communication 6.7 Summary 6.8 Keywords 6.9 Learning Activity 6.10 Unit End Questions 6.11 References 6.0 LEARNING OBJECTIVES After studying this unit, you will be able to: Illustrate the main thread and Java Thread Model Explain the thread Priorities and Synchronization in Java Describe Inter-thread Communication 6.1 INTRODUCTION Often in our applications, we need to be able to do multiple things at the same time. We can achieve this in several ways, but key amongst them is to implement multitasking in some form. Multi-tasking means running multiple tasks at the same time, where each task is performing its work. These tasks typically all run at the same time, reading and writing the same memory and interacting with the same resources, but doing different things. The Java language and its run-time system was designed keeping in mind about multithreading. The run-time system depend upon multithreading. Java provides asynchronous thread environment; this helps to increase the utilization of CPU. CU IDOL SELF LEARNING MATERIAL (SLM) 185
Multithreading is best in all cases in contrast with single-thread model. Single-thread system uses an approach of event loop with polling. According to this approach a single thread in the system runs in an infinite loop. Polling the mechanism, that selects a single event from the event queue to choose what to do next. As the event is selected, then event loop forwards the control to the corresponding required event handler. Nothing else can be happened, until the event handler returns. Because of this CPU time is wasted. Here, only one part of the complete program is dominating the whole system, and preventing the system to execute or start any other process. In single-thread model one thread blocks all other threads until its execution completes. On other waiting or idle thread can start and acquire the resource which is not in use by the current thread. This causes the wastage of resources. Java’s multithreading provides benefit in this area by eliminating the loop and polling mechanism, one thread can be paused without stopping the other parts of the program. If any thread is paused or blocked, still other threads continue to run. 6.2 THE MAIN THREAD When a Java program starts up, one thread begins running immediately. This is usually called the main thread of your program, because it is the one that is executed when your program begins. The main thread is important for two reasons: It is the thread from which other “child” threads will be spawned. Often it must be the last thread to finish execution because it performs various shutdown actions. Although the main thread is created automatically when your program is started, it can be controlled through a Thread object. To do so, you must obtain a reference to it by calling the method currentThread( ), which is a public static member of Thread. Its general form is shown here: static Thread currentThread( ) This method returns a reference to the thread in which it is called. Once you have a reference to the main thread, you can control it just like any other thread. Let’s begin by reviewing the following example: // Controlling the main Thread. class CurrentThreadDemo { public static void main(String args[]) { Thread t = Thread.currentThread(); System.out.println(\"Current thread: \" + t); // change the name of the thread CU IDOL SELF LEARNING MATERIAL (SLM) 186
t.setName(\"My Thread\"); System.out.println(\"After name change: \" + t); try { for(int n = 5; n > 0; n--) { System.out.println(n); Thread.sleep(1000); } } catch (InterruptedException e) { System.out.println(\"Main thread interrupted\"); } } } In this program, a reference to the current thread (the main thread, in this case) is obtained by calling currentThread( ), and this reference is stored in the local variable t. Next, the program displays information about the thread. The program then calls setName( ) to change the internal name of the thread. Information about the thread is then redisplayed. Next, a loop counts down from five, pausing one second between each line. The pause is accomplished by the sleep( ) method. The argument to sleep( ) specifies the delay period in milliseconds. Notice the try/catch block around this loop. The sleep( ) method in Thread might throw an InterruptedException. This would happen if some other thread wanted to interrupt this sleeping one. This example just prints a message if it gets interrupted. In a real program, you would need to handle this differently. Here is the output generated by this program: Current thread: Thread[main,5,main] After name change: Thread[My Thread,5,main] 5 4 3 2 1 Notice the output produced when it is used as an argument to println (). This displays, in order: the name of the thread, its priority, and the name of its group. By default, the name of CU IDOL SELF LEARNING MATERIAL (SLM) 187
the main thread is main. Its priority is 5, which is the default value, and main is also the name of the group of threads to which this thread belongs. A thread group is a data structure that controls the state of a collection of threads as a whole. This process is managed by the particular run-time environment and is not discussed in detail here. After the name of the thread is changed, t is again output. This time, the new name of the thread is displayed. Let’s look more closely at the methods defined by Thread that are used in the program. The sleep( ) method causes the thread from which it is called to suspend execution for the specified period of milliseconds. Its general form is shown here: static void sleep(long milliseconds) throws InterruptedException The number of milliseconds to suspend is specified in milliseconds. This method may throw an InterruptedException. The sleep( ) method has a second form, shown next, which allows you to specify the period in terms of milliseconds and nanoseconds: static void sleep(long milliseconds, int nanoseconds) throws InterruptedException This second form is useful only in environments that allow timing periods as short as nanoseconds. As the preceding program shows, you can set the name of a thread by using setName( ). You can obtain the name of a thread by calling getName( ) (but note that this procedure is not shown in the program). These methods are members of the Thread class and are declared like this: final void setName(String threadName) final String getName( ) Here, threadName specifies the name of the thread. 6.3 JAVA THREAD MODEL The Java run-time system depends on threads for many things, and all the class libraries are designed with multithreading in mind. In fact, Java uses threads to enable the entire environment to be asynchronous. This helps reduce inefficiency by preventing the waste of CPU cycles. The value of a multithreaded environment is best understood in contrast to its counterpart. Single-threaded systems use an approach called an event loop with polling. In this model, a single thread of control runs in an infinite loop, polling a single event queue to decide what to do next. Once this polling mechanism returns with, say, a signal that a network file is ready to be read, then the event loop dispatches control to the appropriate event handler. Until this event handler returns, nothing else can happen in the system. This wastes CPU time. It can also result in one part of a program dominating the system and preventing any other events from being processed. In general, in a singled-threaded environment, when a thread blocks (that is, suspends execution) because it is waiting for some resource, the entire program stops running. The benefit of Java’s multithreading is that the main loop/polling mechanism is eliminated. One thread can pause without stopping other parts of your program. For example, the idle time created when a thread reads data from a network or waits for user input can be utilized elsewhere. Multithreading allows animation loops to sleep for a second between each frame without causing the whole system to pause. CU IDOL SELF LEARNING MATERIAL (SLM) 188
When a thread blocks in a Java program, only the single thread that is blocked pauses. All other threads continue to run. 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. 6.4 THREAD PRIORITIES Java assigns to each thread a priority that determines how that thread should be treated with respect to the others. Thread priorities are integers that specify the relative priority of one thread to another. As an absolute value, a priority is meaningless; a higher-priority thread doesn’t run any faster than a lower-priority thread if it is the only thread running. Instead, a thread’s priority is used to decide when to switch from one running thread to the next. This is called a context switch. The rules that determine when a context switch takes place are simple: A thread can voluntarily relinquish control. This is done by explicitly yielding, sleeping, or blocking on pending I/O. In this scenario, all other threads are examined, and the highest-priority thread that is ready to run is given the CPU. A thread can be pre-empted by a higher-priority thread. In this case, a lower-priority thread that does not yield the processor is simply pre-empted no matter what it is doing by a higher-priority thread. Basically, as soon as a higher-priority thread wants to run, it does. This is called pre-emptive multitasking. In cases where two threads with the same priority are competing for CPU cycles, the situation is a bit complicated. For operating systems such as Windows 98, threads of equal priority are time-sliced automatically in round-robin fashion. For other types of operating systems, threads of equal priority must voluntarily yield control to their peers. If they don’t, the other threads will not run. Problems can arise from the differences in the way those operating systems context-switch threads of equal priority. 6.5 SYNCHRONIZATION IN JAVA Because multithreading introduces an asynchronous behaviour to your programs, there must be a way for you to enforce synchronicity when you need it. For example, if you want two threads to communicate and share a complicated data structure, such as a linked list, you need some way to ensure that they don’t conflict with each other. That is, you must prevent one thread from writing data while another thread is in the middle of reading it. For this purpose, Java implements an elegant twist on an age-old model of interposes synchronization: the CU IDOL SELF LEARNING MATERIAL (SLM) 189
monitor. The monitor is a control mechanism first defined by C.A.R. Hoare. You can think of a monitor as a very small box that can hold only one thread. Once a thread enters a monitor, all other threads must wait until that thread exits the monitor. In this way, a monitor can be used to protect a shared asset from being manipulated by more than one thread at a time. Most multithreaded systems expose monitors as objects that your program must explicitly acquire and manipulate. Java provides a cleaner solution. There is no class “Monitor”; instead, each object has its own implicit monitor that is automatically entered when one of the object’s synchronized methods is called. Once a thread is inside a synchronized method, no other thread can call any other synchronized method on the same object. This enables you to write very clear and concise multithreaded code, because synchronization support is built in to the language. 6.6 INTER-THREAD COMMUNICATION The preceding examples unconditionally blocked other threads from asynchronous access to certain methods. This use of the implicit monitors in Java objects is powerful, but you can achieve a more subtle level of control through interposes communication. As you will see, this is especially easy in Java. As discussed earlier, multithreading replaces event loop programming by dividing your tasks into discrete and logical units. Threads also provide a secondary benefit: they do away with polling. Polling is usually implemented by a loop that is used to check some condition repeatedly. Once the condition is true, appropriate action is taken. This wastes CPU time. For example, consider the classic queuing problem, where one thread is producing some data and another is consuming it. To make the problem more interesting, suppose that the producer has to wait until the consumer is finished before it generates more data. In a polling system, the consumer would waste many CPU cycles while it waited for the producer to produce. Once the producer was finished, it would start polling, wasting more CPU cycles waiting for the consumer to finish, and so on. Clearly, this situation is undesirable. To avoid polling, Java includes an elegant interposes communication mechanism via the wait( ), notify( ), and notify All( ) methods. These methods are implemented as final methods in Object, so all classes have them. All three methods can be called only from within a synchronized context. Although conceptually advanced from a computer science perspective, the rules for using these methods are actually quite simple: Wait ( ) tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify ( ). Notify ( ) wakes up the first thread that called wait ( ) on the same object. Notify All ( ) wakes up all the threads that called wait( ) on the same object. The highest priority thread will run first. These methods are declared within Object, as shown here: CU IDOL SELF LEARNING MATERIAL (SLM) 190
final void wait( ) throws InterruptedException final void notify( ) final void notifyAll( ) Additional forms of wait( ) exist that allow you to specify a period of time to wait. The following sample program incorrectly implements a simple form of the producer/consumer problem. It consists of four classes: Q, the queue that you’re trying to synchronize; Producer, the threaded object that is producing queue entries; Consumer, the threaded object that is consuming queue entries; and PC, the tiny class that creates the single Q, Producer, and Consumer. // An incorrect implementation of a producer and consumer. class Q { int n; synchronized int get() { System.out.println(\"Got: \" + n); return n; } synchronized void put(int n) { this.n = n; System.out.println(\"Put: \" + n); } } class Producer implements Runnable { Q; Producer(Q q) { this.q = q; new Thread(this, \"Producer\").start(); } public void run() { int i = 0; while(true) { CU IDOL SELF LEARNING MATERIAL (SLM) 191
q.put(i++); } } } class Consumer implements Runnable { Q; Consumer(Q q) { this.q = q; new Thread(this, \"Consumer\").start(); } public void run() { while(true) { q.get(); } } } class PC { public static void main(String args[]) { Q = new Q(); new Producer(q); new Consumer(q); System.out.println(\"Press Control-C to stop.\"); } } Although the put( ) and get( ) methods on Q are synchronized, nothing stops the producer from overrunning the consumer, nor will anything stop the consumer from consuming the same queue value twice. Thus, you get the erroneous output shown here (the exact output will vary with processor speed and task load): Put: 1 Got: 1 CU IDOL SELF LEARNING MATERIAL (SLM) 192
Got: 1 Got: 1 Got: 1 Got: 1 Put: 2 Put: 3 Put: 4 Put: 5 Put: 6 Put: 7 Got: 7 6.7 SUMMARY The Java language and its run-time system was designed keeping in mind about multithreading. The run-time system depend upon multithreading. Java provides asynchronous thread environment; this helps to increase the utilization of CPU. Multithreading is best in all cases in contrast with single-thread model. Single-thread system uses an approach of event loop with polling. According to this approach a single thread in the system runs in an infinite loop. When a Java program starts up, one thread begins running immediately. This is usually called the main thread of your program, because it is the one that is executed when your program begins. The Java run-time system depends on threads for many things, and all the class libraries are designed with multithreading in mind. In fact, Java uses threads to enable the entire environment to be asynchronous. This helps reduce inefficiency by preventing the waste of CPU cycles. Java assigns to each thread a priority that determines how that thread should be treated with respect to the others. Thread priorities are integers that specify the relative priority of one thread to another. As an absolute value, a priority is meaningless; a higher-priority thread doesn’t run any faster than a lower-priority thread if it is the only thread running. Instead, a thread’s priority is used to decide when to switch from one running thread to the next. This is called a context switch. CU IDOL SELF LEARNING MATERIAL (SLM) 193
Main thread method returns a reference to the thread in which it is called. Once you have a reference to the main thread, you can control it just like any other thread. Let’s begin by reviewing the following example: Inter thread communication methods are implemented as final methods in Object, so all classes have them. All three methods can be called only from within a synchronized context. Although conceptually advanced from a computer science perspective, the rules for using these methods are actually quite simple: 6.8 KEYWORDS Thread: A thread, in the context of Java, is the path followed when executing a program. ... In Java, creating a thread is accomplished by implementing an interface and extending a class. Every Java thread is created and controlled by the java. lang. Thread class. Main thread: The Main thread in Java is the one that begins executing when the program starts. All the child threads are spawned from the Main thread. Also, it is the last thread to finish execution as various shut-down actions are performed by it. Thread priority: Thread priority in Java is a number assigned to a thread that is used by Thread scheduler to decide which thread should be allowed to execute. In Java, each thread is assigned a different priority that will decide the order (preference) in which it is scheduled for running. Synchronization: Synchronization in java is the capability to control the access of multiple threads to any shared resource. In the Multithreading concept, multiple threads try to access the shared resources at a time to produce inconsistent results. The synchronization is necessary for reliable communication between threads. Inter-thread communication: Cooperation (Inter-thread communication) is a mechanism in which a thread is paused running in its critical section and another thread is allowed to enter (or lock) in the same critical section to be executed. It is implemented by following methods of Object class: wait() notify() 6.9 LEARNING ACTIVITY 1. Discuss the topic the main thread. ________________________________________________________________________ __________________________________________________________________ 2. Conduct a seminar on java thread model. CU IDOL SELF LEARNING MATERIAL (SLM) 194
________________________________________________________________________ __________________________________________________________________ 6.10 UNIT END QUESTIONS A. Descriptive Questions Short Questions: 1. What is the main thread? 2. What is java thread model? 3. What is thread priorities? 4. What is synchronization? 5. What is interring thread communication? Long Questions: 1. What is the main thread explain in detail? 2. What is java thread model explain in detail? 3. What is thread priorities explain in detail? 4. What is synchronization explain in detail? 5. What is inter thread communication explain in detail? B. Multiple Choice Questions 1. What is the name of the method used to start a thread execution? a. Run(); b. Init(); c. Start(); d. Resume(); 2. Which of the following will directly stop the execution of a Thread? a. Notify() b. Notifyall() c. Wait() d. Exits synchronized code 3. How can a thread be created in java multi-threading? a. Extending Thread class CU IDOL SELF LEARNING MATERIAL (SLM) 195
b. Implementing Runnable interface c. Using both d. None 4. Which method is called internally by Thread start() method? a. Execute() b. Run() c. Launch() d. Main() 5. Which method must be implemented by a Java thread? a. Run() b. Execute() c. Start() d. None Answers 1-c, 2-c, 3-c, 4-b, 5-a. 6.11 REFERENCES References Ken Arnold and James Gosling, The Java Programming Language, second ed., Addison-Wesley, 1998. Peter Coad and Mark Mayfield, Java Design: Building Better Apps and Applets, Yourdon Press, 1996. David M. Geary, Graphic Java 2: Mastering the JFC, vol. I, AWT, third ed., Sun Microsystems Press, 1999. Textbooks Graham Hamilton and Rick Cattell and Maydene Fisher, JDBC Database Access with Java: A Tutorial and Annotated Reference, SunSoft Press, 1997. Arnold, Ken, James Gosling and David Holmes (2005). The Java Programming Language, 3rd edition. NJ: Prentice Hall. CU IDOL SELF LEARNING MATERIAL (SLM) 196
Balagurusamy, E. (2007). Programming with JAVA: A Primer, 3rd edition. New Delhi: Tata McGraw-Hill. Website https://www.mygreatlearning.com https://www.w3schools.com https://beginnersbook.com CU IDOL SELF LEARNING MATERIAL (SLM) 197
UNIT – 7:EXCEPTION HANDLING 1 STRUCTURE 7.0 Learning Objectives 7.1 Introduction 7.2 Exception 7.3Handling of Exception 7.4Exception Type 7.5Using try-catch 7.6 Catching Multiple Exceptions 7.7 Summary 7.8 Keywords 7.9 Learning Activity 7.10 Unit End Questions 7.11 References 7.0 LEARNING OBJECTIVES After studying this unit, you will be able to: Illustrate the Exception and handling of Exception Describe the exception type Explain Using try-catchand multiple exceptions 7.1 INTRODUCTION Exception handling is one of the most important features of java programming that allows us to handle the runtime errors caused by exceptions. In this guide, we will learn what is an exception? types of it, exception classes and how to handle exceptions in java with examples. What is an exception? An Exception is an unwanted event that interrupts the normal flow of the program. When an exception occur program execution gets terminated. In such cases we get a system generated error message. The good thing about exceptions is that they can be handled in Java. By CU IDOL SELF LEARNING MATERIAL (SLM) 198
handling the exceptions we can provide a meaningful message to the user about the issue rather than a system generated message, which may not be understandable to a user. Why an exception occurs? There can be several reasons that can cause a program to throw exception. For example: Opening a non-existing file in your program, Network connection problem, bad input data provided by user etc. 7.2 EXCEPTION Like most modern programming languages, Java includes the concept of exceptions to handle both errors and \"exceptional events.\" When an exception occurs in your code, it disrupts the normal instruction logic and abnormally terminates the process. However, with a little foresight and code, you can often handle these exceptions gracefully, allowing your code to continue running and providing insight for tracking down the root cause of the unexpected result. In this article, we’ll take a brief look at how Java handles exceptions, the difference between checked and unchecked exceptions, and then walk through ten of the most common exceptions you’ll face in Java, and why they might occur. Checked versus Unchecked Java Exceptions Java exceptions can be broken down into one of three categories: Checked - these are exceptions that are checked by the compiler at compile time. These exceptions must be caught by a try/catch in the code or noted as thrown by the method. For instance, if a program attempts to access a file that is currently unavailable, the method to access the file must either catch or throw a FileNotFoundException. Error - errors are exceptions that happen externally to your Java program. One common example of the error is when the Java virtual machine runs out of memory, which will throw an OutOfMemoryError. Runtime - runtime exceptions are internal to your application but are not typically recoverable. For example, an object that is expected to have a value but is actually null. In this case, a NullPointerException exception would be thrown. Often, these three categories are broken down into checked and unchecked classificationserror and runtime exceptions are grouped together as unchecked, which, per their name, are not checked at compile time and can result in runtime errors. Now let’s walk through some of the most common Checked and Unchecked exceptions you’re likely to encounter in Java. Checked Exceptions CU IDOL SELF LEARNING MATERIAL (SLM) 199
Let's start by looking at some of the most common checked exceptions in Java. 1. ClassNotFoundException The ClassNotFoundException happens when a required class cannot be found on the class path. The most common situation where the ClassNotFoundException occurs is when an external dependency is not available, which stems from application misconfiguration. In Maven-based projects, for example, this would translate to a missing or misconfigured <--- dependency--->. The easiest way to reproduce this error is to simply delete a required .class file of a previously-running program. When the program attempts to make a call to a method inside the deleted .class file, it will throw the ClassNotFoundException. 2. InvocationTargetException The InvocationTargetException is related to the reflection functionality of Java and occurs when trying to invoke a method or constructor that results in throwing an exception. To illustrate, consider the following class: public class Example { public int divide(int numerator) { return numerator / 0; } } The divide() method includes an input number (numerator), but the denominator is fixed at zero, which will produce a divide by zero error (ArithmeticException). The InvocationTargetExceptioncode> error occurs when using reflection to invoke the method: Example = new Example(); Method = Example.class.getMethod(\"divide\"); Exception = assertThrows(Example.class, () -> method.invoke(example)); Since the InvocationTargetException is in the reflection layer, the ArithmeticException is wrapped inside this provided exception. 3. InterruptedException Every thread has a boolean interrupt property used as an internal flag representing its interrupted status. This property provides a way for threads to interrupt—or stop—other threads/tasks. CU IDOL SELF LEARNING MATERIAL (SLM) 200
Search
Read the Text Version
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334