Unit - 2
Multi-Threading
In Java, multithreading is the process of running several threads at the same time.
A thread is the smallest unit of processing and is a lightweight sub-process. Multitasking is accomplished through the use of multiprocessing and multithreading.
Because threads share memory, we employ multithreading rather than multiprocessing. They conserve memory by not allocating a separate memory space, and context-switching between threads takes less time than processing.
Multithreading in Java is typically utilized in gaming, animation, and other similar applications.
Because Java is a multi-threaded programming language, we can use it to create multi-threaded programs. A multi-threaded program is made up of two or more portions that can operate in parallel, each of which can tackle a distinct task at the same time, maximizing the use of available resources, especially when your computer has several CPUs.
Multitasking is defined as the sharing of common processing resources, such as a CPU, by many processes. Multi-threading extends the concept of multitasking into programs by allowing you to divide certain operations within a single app into several threads. Each thread can execute in its own thread. Not only does the operating system split processing time among distinct apps, but it also divides it among each thread within an application.
Multi-threading allows you to write software in which multiple activities can run at the same time.
Life cycle of a Thread
In its life cycle, a thread travels through several stages. A thread, for example, gets born, starts, runs, and eventually dies. The graphic below depicts a thread's whole life cycle.
Fig 1: life cycle of a thread
The stages of the life cycle are listed below.
New – In the new state, a new thread begins its life cycle. It will stay in this state until the thread is started by the program. A born thread is another name for it.
Runnable – When a freshly created thread is initiated, it becomes runnable. When a thread is in this position, it is regarded to be doing its job.
Waiting – When a thread is waiting for another thread to complete a job, it may shift to the waiting state. Only when another thread signals the waiting thread to continue executing does a thread transition back to the runnable state.
Timed waiting – A runnable thread can go into a timed waiting state for a set amount of time. When the time period expires or the event it is waiting for occurs, a thread in this state moves back to the runnable state.
Terminated (Dead) – When a runnable thread completes its task or otherwise terminates, it enters the terminated state.
Advantages of multithreading
● Because threads are autonomous and many operations can be performed at the same time, it does not cause the user to be blocked.
● It saves time by allowing you to do multiple procedures at once.
● Because threads are self-contained, an exception in one thread has no impact on other threads.
Key takeaway
- Multithreading is the process of running several threads at the same time.
- Multithreading in Java is typically utilized in gaming, animation, and other similar applications.
- A multi-threaded program is made up of two or more portions that can operate in parallel, each of which can tackle a distinct task at the same time, maximizing the use of available resources, especially when your computer has several CPUs.
Every Java thread has a priority, which aids the operating system in determining the thread scheduling order.
There is a priority for each thread. Priorities are assigned a number between one and ten. Thread scheduling, in most circumstances, schedules threads according to their priority (known as preemptive scheduling). However, it is not assured because the scheduling option used by the JVM is dependent on the JVM specification.
Thread class defines three constants:
● public static int MIN_PRIORITY
● public static int NORM_PRIORITY
● public static int MAX_PRIORITY
The range of Java thread priorities is between MIN PRIORITY (a constant of 1) and MAX PRIORITY (a constant of 2). (a constant of 10). NORM PRIORITY is the default priority for all threads (a constant of 5).
Higher-priority threads are more vital to a program and should be given priority over lower-priority threads. Thread priorities, on the other hand, cannot ensure the order in which threads execute and are very platform dependent.
Example
Class TestMultiPriority1 extends Thread{
Public void run(){
System.out.println("running thread name is:"+Thread.currentThread().getName());
System.out.println("running thread priority is:"+Thread.currentThread().getPriority());
}
Public static void main(String args[]){
TestMultiPriority1 m1=new TestMultiPriority1();
TestMultiPriority1 m2=new TestMultiPriority1();
m1.setPriority(Thread.MIN_PRIORITY);
m2.setPriority(Thread.MAX_PRIORITY);
m1.start();
m2.start();
}
}
Output
Running thread name is: Thread-0
Running thread priority is:10
Running thread name is: Thread-1
Running thread priority is:1
Key takeaway
There is a priority for each thread. Priorities are assigned a number between one and ten. Thread scheduling, in most circumstances, schedules threads according to their priority.
When we start two or more threads in a program, it's possible that numerous threads will try to access the same resource, resulting in unexpected results due to concurrency difficulties. For example, if multiple threads try to write to the same file at the same time, the data may be corrupted because one of the threads can override data, or while one thread is opening and another is closing the same file.
As a result, it's necessary to synchronize many threads' actions and ensure that only one thread can access the resource at any given time. This is accomplished through the use of monitors. In Java, each object has its own monitor, which a thread can lock or unlock. On a display, only one thread can retain a lock at a time.
Using synchronized blocks, the Java programming language makes it relatively easy to create threads and synchronize their tasks. Within this block, you retain shared resources. The general form of the synchronized statement is as follows:
Syntax
Synchronized(objectidentifier)
{
// Access shared variables and other shared resources
}
The object identifier is a reference to an object whose lock corresponds to the monitor represented by the synchronized statement. Now we'll look at two different ways to print a counter using two distinct threads. When threads are not synchronized, they publish counter values that are out of order, but when we print counter inside a synchronized() block, it prints counters that are very much in order for both threads.
Multithreading Example with synchronization
Class PrintDemo {
Public void printCount() {
Try {
For(int i = 5; i > 0; i--) {
System.out.println("Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
Class ThreadDemo extends Thread {
Private Thread t;
Private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd) {
ThreadName = name;
PD = pd;
}
Public void run() {
Synchronized(PD) {
PD.printCount();
}
System.out.println("Thread " + threadName + " exiting.");
}
Public void start () {
System.out.println("Starting " + threadName );
If (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
Public class TestThread {
Public static void main(String args[]) {
PrintDemo PD = new PrintDemo();
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD );
T1.start();
T2.start();
// wait for threads to end
Try {
T1.join();
T2.join();
} catch ( Exception e) {
System.out.println("Interrupted");
}
}
}
Output
Starting Thread - 1
Starting Thread - 2
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 1 exiting.
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 2 exiting.
Key takeaway
Using synchronized blocks, the Java programming language makes it relatively easy to create threads and synchronize their tasks. Within this block, you retain shared resources.
A thread can be made in two ways:
- By extending Thread class
- By implementing Runnable interface.
By extending Thread class
Method for creating a thread is to use the two simple steps below to construct a new class that extends the Thread class. This technique allows you more flexibility when dealing with multiple threads established with the Thread class's various methods.
Step 1:
You'll need to override the Thread class's run( ) method. This method serves as the thread's entry point, and it's where you'll put all of your business logic. The run() method has the following simple syntax:
Public void run( )
Step 2:
You can start a Thread object by executing the start() method, which executes a call to the run() method. The start() method has the following simple syntax:
Void start( );
Example
Class ThreadDemo extends Thread {
Private Thread t;
Private String threadName;
ThreadDemo( String name) {
ThreadName = name;
System.out.println("Creating " + threadName );
}
Public void run() {
System.out.println("Running " + threadName );
Try {
For(int i = 4; i > 0; i--) {
System.out.println("Thread: " + threadName + ", " + i);
// Let the thread sleep for a while.
Thread.sleep(50);
}
} catch (InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
Public void start () {
System.out.println("Starting " + threadName );
If (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
Public class TestThread {
Public static void main(String args[]) {
ThreadDemo T1 = new ThreadDemo( "Thread-1");
T1.start();
ThreadDemo T2 = new ThreadDemo( "Thread-2");
T2.start();
}
}
Output
Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.
By implementing Runnable interface
If you want your class to be run as a thread, you can do so by implementing the Runnable interface. You'll need to take three basic actions to get started.
Step 1:
You must first implement the run() method given by the Runnable interface. This method serves as the thread's entry point, and it's where you'll put all of your business logic. The run() method has the following simple syntax:
Public void run( )
Step 2:
In the next step, you'll create a Thread object with the constructor below.
Thread(Runnable threadObj, String threadName);
ThreadObj is an instance of a class that implements the Runnable interface, and threadName is the new thread's name.
Step 3:
You can start a Thread object by executing the start() method, which executes a call to the run( ) method. The start() method has the following simple syntax:
Void start();
Example
Class RunnableDemo implements Runnable {
Private Thread t;
Private String threadName;
RunnableDemo( String name) {
ThreadName = name;
System.out.println("Creating " + threadName );
}
Public void run() {
System.out.println("Running " + threadName );
Try {
For(int i = 4; i > 0; i--) {
System.out.println("Thread: " + threadName + ", " + i);
// Let the thread sleep for a while.
Thread.sleep(50);
}
} catch (InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
Public void start () {
System.out.println("Starting " + threadName );
If (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
Public class TestThread {
Public static void main(String args[]) {
RunnableDemo R1 = new RunnableDemo( "Thread-1");
R1.start();
RunnableDemo R2 = new RunnableDemo( "Thread-2");
R2.start();
}
}
Output
Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.
Let’s see how to create multiple threads
Example
Class MyThread implements Runnable {
String name;
Thread t;
MyThread String thread){
Name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start();
}
Public void run() {
Try {
For(int i = 5; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(1000);
}
}catch (InterruptedException e) {
System.out.println(name + "Interrupted");
}
System.out.println(name + " exiting.");
}
}
Class MultiThread {
Public static void main(String args[]) {
New MyThread("One");
New MyThread("Two");
New NewThread("Three");
Try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
Output
New thread: Thread[One,5,main]
New thread: Thread[Two,5,main]
New thread: Thread[Three,5,main]
One: 5
Two: 5
Three: 5
One: 4
Two: 4
Three: 4
One: 3
Three: 3
Two: 3
One: 2
Three: 2
Two: 2
One: 1
Three: 1
Two: 1
One exiting.
Two exiting.
Three exiting.
When one thread needs to know when another thread is terminating, it can be useful. In Java, the methods isAlive() and join() are used to determine whether or not a thread has completed its execution.
If the thread on which it is called is still running, the isAlive() method returns true; otherwise, it returns false.
Final boolean isAlive()
However, the join() technique is more widely used than the isAlive() function (). This procedure waits for the thread that called it to finish.
Final void join() throws InterruptedException
We tell our thread to wait until the provided thread completes its execution using the join() method. There are overloaded variants of the join() method that allow us to define the amount of time we want to wait for a thread to finish.
Final void join(long milliseconds) throws Interrupted Exception
Example (isAlive())
Public class MyThread extends Thread
{
Public void run()
{
System.out.println("r1 ");
Try {
Thread.sleep(500);
}
Catch(InterruptedException ie)
{
// do something
}
System.out.println("r2 ");
}
Public static void main(String[] args)
{
MyThread t1=new MyThread();
MyThread t2=new MyThread();
t1.start();
t2.start();
System.out.println(t1.isAlive());
System.out.println(t2.isAlive());
}
}
Output
r1
True
True
r1
r2
r2
Example (join())
Public class MyThread extends Thread
{
Public void run()
{
System.out.println("r1 ");
Try {
Thread.sleep(500);
}catch(InterruptedException ie){ }
System.out.println("r2 ");
}
Public static void main(String[] args)
{
MyThread t1=new MyThread();
MyThread t2=new MyThread();
t1.start();
Try{
t1.join(); //Waiting for t1 to finish
}catch(InterruptedException ie){}
t2.start();
}
}
Output
r1
r2
r1
r2
Wait() and notify()
The wait() and notify() methods in Java allow threads to communicate with one another. These are final methods in the Object class that can only be called from a synchronized context. The wait() method makes the current thread wait until another thread calls the object's notify() methods. The notify() method starts a single thread that is waiting on the monitor of that object. By invoking one of the wait() methods, a thread can wait on an object's monitor. If the current thread is not the owner of the object's monitor, these methods may throw IllegalMonitorStateException.
Syntax for wait()
Public final void wait() throws InterruptedException
Syntax for notify()
Public final void notify()
Example
Public class WaitNotifyTest {
Private static final long SLEEP_INTERVAL = 3000;
Private boolean running = true;
Private Thread thread;
Public void start() {
Print("Inside start() method");
Thread = new Thread(new Runnable() {
@Override
Public void run() {
Print("Inside run() method");
Try {
Thread.sleep(SLEEP_INTERVAL);
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
Synchronized(WaitNotifyTest.this) {
Running = false;
WaitNotifyTest.this.notify();
}
}
});
Thread.start();
}
Public void join() throws InterruptedException {
Print("Inside join() method");
Synchronized(this) {
While(running) {
Print("Waiting for the peer thread to finish.");
Wait(); //waiting, not running
}
Print("Peer thread finished.");
}
}
Private void print(String s) {
System.out.println(s);
}
Public static void main(String[] args) throws InterruptedException {
WaitNotifyTest test = new WaitNotifyTest();
Test.start();
Test.join();
}
}
Output
Inside start() method
Inside join() method
Waiting for the peer thread to finish.
Inside run() method
Peer thread finished.
Key takeaway
If the thread on which it is called is still running, the isAlive() method returns true; otherwise, it returns false.
There are overloaded variants of the join() method that allow us to define the amount of time we want to wait for a thread to finish.
The wait() and notify() methods in Java allow threads to communicate with one another.
These are final methods in the Object class that can only be called from a synchronized context.
In Java APIs, the String class provides a variety of constructors.
The constructors of the String class that are most typically used are as follows:
● String()
● String(String str)
● String(char chars[ ])
● String(char chars[ ], int startIndex, int count)
● String(byte byteArr[ ])
● String(byte byteArr[ ], int startIndex, int count)
String() - We'll use the default constructor to make an empty String. The following is the usual syntax for creating an empty string in a Java program:
String s = new String();
It will generate a string object with no value in the memory region.
String(String str) - In the heap region, it will build a string object and store the specified value in it. The following is the standard syntax for creating a string object with a provided string str:
String st = new String(String str);
For example:
String s2 = new String("Hello Java");
Hello Java is included in the object str.
String(char chars[ ]) - The array of characters is stored in a string object created by this constructor. The following is the basic syntax for creating a string object with a provided array of characters:
String str = new String(char char[])
For example:
Char chars[ ] = { 'a', 'b', 'c', 'd' };
String s3 = new String(chars);
The address of the value stored in the heap area is kept in the object reference variable s3.
String(char chars[ ], int startIndex, int count) - With a subrange of a character array, this constructor builds and initializes a string object.
The startIndex and count arguments specify the index at which the subrange begins and the number of characters to be copied, respectively.
The following is the standard syntax for creating a string object with the specified subrange of a character array:
String str = new String(char chars[ ], int startIndex, int count);
For example:
Char chars[ ] = { 'w', 'i', 'n', 'd', 'o', 'w', 's' };
String str = new String(chars, 2, 3);
Because the starting index is 2 and the total number of characters to be copied is 3, the object str contains the address of the value "ndo" stored in the heap region.
String(byte byteArr[ ]) - This constructor creates a new string object by decoding the given array of bytes (i.e., ASCII values into characters) using the system's default character set.
Example
Package stringPrograms;
Public class ByteArray
{
Public static void main(String[] args)
{
Byte b[] = { 97, 98, 99, 100 }; // Range of bytes: -128 to 127. These byte values will be converted into corresponding characters.
String s = new String(b);
System.out.println(s);
}
}
Output:
Abcd
String(byte byteArr[ ], int startIndex, int count) - The ASCII values are decoded using the system's default character set, and a new string object is created.
Example
Package stringPrograms;
Public class ByteArray
{
Public static void main(String[] args)
{
Byte b[] = { 65, 66, 67, 68, 69, 70 }; // Range of bytes: -128 to 127.
String s = new String(b, 2, 4); // CDEF
System.out.println(s);
}
}
Output
CDEF
This method returns the string's length. The length of the string is equal to the number of 16-bit Unicode characters.
Syntax
Public int length()
Example
public class Stringoperation5
{
Public static void main(String ar[])
{
String s="Sachin";
System.out.println(s.length());//6
}
}
Output
6
Characters can be taken from a String object in a variety of ways using the String class. Despite the fact that the characters that make up a string within a String object cannot be indexed like a character array, many String methods use an index (or offset) into the string to perform their operations. String indexes, like array indexes, start at zero.
CharAt()
To extract a single character from a String, use the charAt( ) function to refer to a particular character. It takes the following general form:
Char charAt(int where)
Where is the index of the character you're looking for? Where must be a nonnegative value and must specify a position within the string. The character at the provided place is returned by charAt(). As an example,
Char ch;
Ch = "abc".charAt(1);
Assigns the value b to ch.
GetChars()
The getChars() method can be used to retrieve more than one character at a time. It takes the following general form:
Void getChars(int sourceStart, int sourceEnd, char target[ ], int targetStart)
Here, sourceStart gives the index of the desired substring's beginning, and sourceEnd specifies the index of the desired substring's finish. As a result, the substring includes characters from sourceStart to sourceEnd–1. Target specifies the array that will receive the characters. TargetStart specifies the index within target where the substring will be copied. It's important to double-check that the target array can accommodate the number of characters in the supplied substring.
Example
Lass getCharsDemo {
Public static void main(String args[]) {
String s = "This is a demo of the getChars method.";
Int start = 10;
Int end = 14;
Char buf[] = new char[end - start];
s.getChars(start, end, buf, 0); System.out.println(buf);
}
}
Output
Demo
GetBytes()
The characters are stored in an array of bytes as an alternative to getChars(). This method is named getBytes(), and it employs the platform's default character-to-byte conversions. In its most basic form, it looks like this:
Byte[ ] getBytes( )
Other getBytes() variants are also available. When you're exporting a String value into an environment that doesn't handle 16-bit Unicode characters, getBytes() comes in handy. For example, for all text interchange, most Internet protocols and text file formats employ 8-bit ASCII.
ToCharArray( )
The simplest way to convert all the characters in a String object into a character array is to use the toCharArray method ( ). For the full string, it returns an array of characters. It takes the following general form:
Char[ ] toCharArray( )
Because getChars() may achieve the same effect, this function is just offered as a convenience.
Key takeaway
Characters can be taken from a String object in a variety of ways using the String class.
Despite the fact that the characters that make up a string within a String object cannot be indexed like a character array, many String methods use an index (or offset) into the string to perform their operations.
String indexes, like array indexes, start at zero.
In Java, we can compare Strings based on their content and references.
It's utilized for things like authentication (using the equals() method), sorting (using the compareTo() method), and reference matching (using the == operator).
In Java, there are three techniques to compare strings:
● By Using equals() Method
● By Using == Operator
● By compareTo() Method
By using equals () methods
The equals() function of the String class compares the string's original content. It compares string values for equality. Two methods are available in the String class:
● public boolean equals(Object another) compares this string to the specified object.
● public boolean equalsIgnoreCase(String another) compares this string to another string, ignoring case.
Example
Class Teststringcomparison2{
Public static void main(String args[]){
String s1="Sachin";
String s2="SACHIN";
System.out.println(s1.equals(s2));//false
System.out.println(s1.equalsIgnoreCase(s2));//true
}
}
Output
False
True
The methods of the String class are used in the given program. If two String objects are equal and have the same case, the equals() function returns true. Regardless of the case of strings, equalsIgnoreCase() returns true.
By using == operators
The == operator compares references to each other rather than values.
Example
Class Teststringcomparison3{
Public static void main(String args[]){
String s1="Sachin";
String s2="Sachin";
String s3=new String("Sachin");
System.out.println(s1==s2);//true (because both refer to same instance)
System.out.println(s1==s3);//false(because s3 refers to instance created in nonpool)
}
}
Output
True
False
By Using compareTo() method
The compareTo() method of the String class compares two strings lexicographically and returns an integer value indicating whether the first string is less than, equal to, or greater than the second string.
Assume that s1 and s2 are two different String objects. If:
● s1 == s2: The method returns 0.
● s1 > s2: The method returns a positive value.
● s1 < s2: The method returns a negative value.
Example
Class Teststringcomparison4{
Public static void main(String args[]){
String s1="Sachin";
String s2="Sachin";
String s3="Ratan";
System.out.println(s1.compareTo(s2));//0
System.out.println(s1.compareTo(s3));//1(because s1>s3)
System.out.println(s3.compareTo(s1));//-1(because s3 < s1 )
}
}
Output
0
1
-1
Because String objects are immutable, modifying a String requires either copying it into a StringBuffer or StringBuilder, or calling a String method that creates a new copy of the string with your changes applied.
Substring()
Substring can be used to extract a substring ( ). It comes in two varieties. The first is this:
String substring(int startIndex)
The index at which the substring will begin is specified by startIndex. This form returns a duplicate of the substring that starts at startIndex and ends at the invoking string's end.
The second form of substring( ) lets you to specify the substring's start and end indexes:
String substring(int startIndex, int endIndex)
The initial index is specified by startIndex, while the ending index is specified by endIndex. The string returned contains all of the characters from the start index to the finish index, but not including them.
Substring() is used in the following software to replace all instances of one substring with another within a string:
// Substring replacement.
Class StringReplace {
Public static void main(String args[]) {
String org = "This is a test. This is, too.";
String search = "is";
String sub = "was"; String result = ""; int i;
Do { // replace all matching substrings
System.out.println(org);
i = org.indexOf(search); if(i != -1) {
Result = org.substring(0, i); result = result + sub;
Result = result + org.substring(i + search.length()); org = result;
}
} while(i != -1);
}
}
Output
This is a test. This is, too.
Thwas is a test. This is, too.
Thwas was a test. This is, too.
Thwas was a test. Thwas is, too.
Thwas was a test. Thwas was, too.
Concat()
Concat() is used to join two strings together, as shown here: string concatenation (String str)
This method returns a new object with the invoking string appended to the end and the contents of str appended to the beginning. The function concat() performs is the same as +.
Example
String s1 = "one";
String s2 = s1.concat("two");
s2 is filled with the string "onetwo." It yields the same result as the sequence below:
String s1 = "one";
String s2 = s1 + "two";
Replace()
There are two versions of the replace() method. The first swaps out all instances of one character in the invoking string for another. Its general shape is as follows:
String replace(char original, char replacement)
The character to be replaced by the character given by replacement is specified by original. The returned string is the result of the operation. As an example,
String s = "Hello".replace('l', 'w');
s is filled with the string "Hewwo."
Replace(second )'s variant swaps out one character sequence for another. It takes the following general form:
String replace(CharSequence original, CharSequence replacement)
Trim()
The trim() method returns a copy of the invoking string that has been stripped of any leading and following whitespace. It takes the following general form:
Trim the strings ( ) Here's an illustration:
String s = " Hello World ".trim();
The string "Hello World" is now in s.
When processing user commands, the trim() technique comes in handy. For instance, the following application asks the user for the name of a state before displaying the capital of that state. Trim( ) is used to eliminate any preceding or trailing whitespace that the user may have entered inadvertently.
// Using trim() to process commands.
Import java.io.*;
Class UseTrim {
Public static void main(String args[]) throws IOException
{
// create a BufferedReader using System.
In BufferedReader br = new
BufferedReader(new InputStreamReader(System.in)); String str;
System.out.println("Enter 'stop' to quit.");
System.out.println("Enter State: ");
Do {
Str = br.readLine();
Str = str.trim(); // remove whitespace
If(str.equals("Illinois")) System.out.println("Capital is Springfield.");
Else if(str.equals("Missouri")) System.out.println("Capital is Jefferson City.");
Else if(str.equals("California")) System.out.println("Capital is Sacramento.");
Else if(str.equals("Washington")) System.out.println("Capital is Olympia.");
// ...
} while(!str.equals("stop"));
}
}
Key takeaway
Because String objects are immutable, modifying a String requires either copying it into a StringBuffer or StringBuilder, or calling a String method that creates a new copy of the string with your changes applied.
The following are the I/O classes specified by java.io:
● BufferedInputStream
● BufferedOutputStream
● BufferedReader
● BufferedWriter
● ByteArrayInputStream
● ByteArrayOutputStream
● CharArrayReader
● CharArrayWriter
● Console
● DataInputStream
● DataOutputStream
● File
● FileDescriptor
● FileInputStream
● FileOutputStream
● FilePermission
● FileReader
● FileWriter
● FilterInputStream
● FilterOutputStream
● FilterReader
● FilterWriter
● InputStream
● InputStreamReader
● LineNumberReader
● ObjectInputStream
● ObjectInputStream.GetField
● ObjectOutputStream
● ObjectOutputStream.PutField
● ObjectStreamClass
● ObjectStreamField
● OutputStream
● OutputStreamWriter
● PipedInputStream
● PipedOutputStream
● PipedReader
● PipedWriter
● PrintStream
● PrintWriter
● PushbackInputStream
● PushbackReader
● RandomAccessFile
● Reader
● SequenceInputStream
● SerializablePermission
● StreamTokenizer
● StringReader
● StringWriter
● Writer
LineNumberInputStream and StringBufferInputStream are two deprecated classes in the java.io package that are not shown in the preceding table. For new programming, these classes should not be utilized.
Java.io defines the following interfaces:
● Closeable
● DataInput
● DataOutput
● Externalizable
● FileFilter
● FilenameFilter
● Flushable
● ObjectInput
● ObjectInputValidation
● ObjectOutput
● ObjectStreamConstants
● Serializable
As you can see, the java.io package contains a large number of classes and interfaces. Byte and character streams, as well as object serialization, are examples (the storage and retrieval of objects).
Streams are used by Java programs to execute I/O. A stream is a type of abstraction that can either produce or receive data. The Java I/O system connects a stream to a physical device. Even though the physical devices to which they are connected differ, all streams perform in the same way. As a result, the same I/O classes and methods can be used on a variety of devices.
This means that an input stream can abstract input from a disk file, a keyboard, or a network socket, among other sources. A console, a disk file, or a network connection are all examples of output streams. Streams are a simple way to handle input/output without having to have every element of your code understand the difference between, say, a keyboard and a network. Streams are implemented in Java using the java.io package's class hierarchies.
Java distinguishes between byte and character streams. Byte streams are a useful way to handle bytes' input and output. When reading or writing binary data, for example, byte streams are employed. Character streams are a useful way to handle character input and output. They are Unicode-based and so internationalizable. Character streams are also more efficient than byte streams in some instances.
Character streams were not included in the first version of Java (Java 1.0), hence all I/O was byte-oriented. Java 1.1 introduced character streams, and several byte-oriented classes and methods were deprecated. Despite the fact that outdated code that does not use character streams is becoming increasingly rare, it can still be seen on occasion. Old code should, in general, be updated to take advantage of character streams wherever possible.
Another point: all I/O is still byte-oriented at the lowest level. Character-based streams are just a more convenient and efficient way of dealing with characters.
Key takeaway
Streams are used by Java programs to execute I/O. A stream is a type of abstraction that can either produce or receive data.
The Java I/O system connects a stream to a physical device.
Even though the physical devices to which they are connected differ, all streams perform in the same way.
Two class hierarchies are used to define byte streams. Two abstract classes, Input Stream and Output Stream, are at the top of the hierarchy. Each of these abstract classes includes multiple concrete subclasses that deal with the differences between different devices like disk files, network connections, and even memory buffers. Table lists the byte stream classes in java.io. Later in this section, we'll go through a number of these classes.
Fig 2: Byte stream classes
Input Stream and Output Stream are abstract classes that specify numerous fundamental methods that the other stream types implement. Read() and write() are two of the most important functions, which read and write bytes of data, respectively. Each one has an abstract form that derived stream classes must override.
Key takeaway
Two class hierarchies are used to define byte streams. Two abstract classes, Input Stream and Output Stream, are at the top of the hierarchy.
Two class hierarchies are used to define character streams. Two abstract classes are at the top: Reader and Writer. Unicode character streams are handled by these abstract classes. Each of these has multiple concrete subclasses in Java. Table lists the character stream classes in java.io.
Fig 3: Character stream I/O classes
The abstract classes are the kind of classes that aren't Reader and Writer specify various fundamental methods that are implemented by the other stream classes. Read() and write() are two of the most important methods for reading and writing data characters, respectively. Each one has an abstract form that derived stream classes must override.
Key takeaway
Two class hierarchies are used to define character streams. Two abstract classes are at the top: Reader and Writer. Unicode character streams are handled by these abstract classes.
An object can be represented as a sequence of bytes that includes the object's data as well as information about the object's type and the types of data stored in the object using Java's object serialization method.
A serialized object can be read from a file and deserialized, which means that the type information and bytes that represent the object and its data can be used to rebuild the object in memory.
The fact that the entire process is JVM independent is particularly interesting, as an object can be serialized on one platform and deserialized on another.
The high-level streams ObjectInputStream and ObjectOutputStream include the methods for serializing and deserializing an object.
Many write methods for writing various data types are available in the ObjectOutputStream class, but one method in particular stands out.
Public final void writeObject(Object x) throws IOException
An Object is serialized and sent to the output stream using the procedure above. Deserializing an object is also possible with the ObjectInputStream class, which has the following method:
Public final Object readObject() throws IOException, ClassNotFoundException
This function deserializes and retrieves the next Object from the stream. Because the return value is an Object, you'll need to cast it to the right data type.
Let's pretend we have the Employee class, which implements the Serializable interface:
Example
Public class Employee implements java.io.Serializable {
Public String name;
Public String address;
Public transient int SSN;
Public int number;
Public void mailCheck() {
System.out.println("Mailing a check to " + name + " " + address);
}
}
There are two conditions that must be met for a class to be serialized successfully:
● The java.io.Serializable interface must be implemented by the class.
● Serializability is required for all fields in the class. A field must be designated transitory if it is not serializable.
If you want to know whether a Java Standard Class is serializable or not, look at its documentation. The test is straightforward: The class is serializable if it implements java.io.Serializable; otherwise, it is not.
Serializing an Object
To serialize an Object, use the ObjectOutputStream class. The Employee object is created and serialized to a file using the SerializeDemo application.
A file entitled employee.ser is created when the software is finished running. The program does not produce any output; instead, examine the code and try to figure out what it is doing.
Example
Import java.io.*;
Public class SerializeDemo {
Public static void main(String [] args) {
Employee e = new Employee();
e.name = "Reyan Ali";
e.address = "Phokka Kuan, Ambehta Peer";
e.SSN = 11122333;
e.number = 101;
Try {
FileOutputStream fileOut =
New FileOutputStream("/tmp/employee.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
Out.writeObject(e);
Out.close();
FileOut.close();
System.out.printf("Serialized data is saved in /tmp/employee.ser");
} catch (IOException i) {
i.printStackTrace();
}
}
}
Key takeaway
A serialized object can be read from a file and deserialized, which means that the type information and bytes that represent the object and its data can be used to rebuild the object in memory.
Java Database Connectivity (JDBC) is an acronym for Java Database Connectivity. JDBC is a Java API for connecting to a database and running queries on it. It's a component of JavaSE (Java Standard Edition). To connect to a database, the JDBC API utilizes JDBC drivers.
The JDBC API can be used to access tabular data in any relational database. We may store, update, remove, and get data from the database using the JDBC API. It's similar to Microsoft's Open Database Connectivity (ODBC).
Fig 4: JDBC
JDBC is a specification that defines a complete set of interfaces for accessing an underlying database from a mobile device. Java can be used to create a variety of executables, including
● Java Applications
● Java Applets
● Java Servlets
● Java Server Pages (JSPs)
● Enterprise JavaBeans (EJBs).
All of these executables can utilize a JDBC driver to connect to a database and use the information contained there.
JDBC is similar to ODBC in that it allows Java programs to contain database-independent code.
JDBC driver
For connecting with your database server, DBC drivers implement the stated interfaces in the JDBC API.
JDBC drivers, for example, allow you to open database connections and interact with them by delivering SQL or database commands and then getting the results in Java.
The Java.sql package that comes with JDK has a number of classes that have their behavior defined but are implemented by third-party drivers. The java.sql.Driver interface is implemented by third-party database drivers.
JDBC driver types
Because Java runs on a wide range of operating systems and hardware platforms, JDBC driver implementations differ. Sun has separated the implementation types into four groups, which are described below: Types 1, 2, 3, and 4.
Type I - JDBC-ODBC Bridge Driver
A JDBC bridge is used in a Type 1 driver to access ODBC drivers installed on each client system. ODBC requires that you set up a Data Source Name (DSN) on your system that reflects the target database.
This was a helpful driver when Java first came out because most databases only supported ODBC access, but it is currently only suggested for experimental use or when no other option is available.
Fig 5: Type I drivers
A good example of this type of driver is the JDBC-ODBC Bridge included with JDK 1.2.
Type II − JDBC-Native API
JDBC API calls are transformed into native C/C++ API calls that are specific to the database in a Type 2 driver. Database suppliers often provide these drivers, which are used in the same way as the JDBC-ODBC Bridge. Each client machine must have the vendor-specific driver loaded.
If we update the database, we must also modify the native API, as it is database-specific. Although Type 2 drivers reduce ODBC's overhead, they may provide a speed boost.
Fig 6: Type II drivers
Type 2 drivers include the Oracle Call Interface (OCI) driver.
Type III − JDBC-Net pure Java
A three-tier technique is utilized to access databases in a Type 3 driver. To connect with a middleware application server, JDBC clients use conventional network sockets. The middleware application server then converts the socket information into the call format required by the DBMS and sends it to the database server.
This type of driver is particularly versatile because it doesn't require any client code and can access multiple databases with only one driver.
Fig 7: Type III drivers
The application server functions as a JDBC "proxy," making calls on behalf of the client application. As a result, in order to use this driver type efficiently, you must have some understanding of the application server's setup.
Understanding the differences between Type 1, 2, and 4 drivers used by your application server to interface with the database may be beneficial.
Type IV − 100% Pure Java
A pure Java-based Type 4 driver uses a socket connection to interface directly with the vendor's database. This is the highest-performance database driver available, and it's normally given by the vendor.
This type of driver is particularly versatile, as it does not require the installation of any additional software on the client or server. Furthermore, these drivers can be dynamically downloaded.
Fig 8: Type IV drivers
The Connector/J driver for MySQL is a Type 4 driver. Database suppliers typically provide type 4 drivers due to the proprietary nature of their network protocols.
Key takeaway
Java Database Connectivity (JDBC) is an acronym for Java Database Connectivity. JDBC is a Java API for connecting to a database and running queries on it. It's a component of JavaSE (Java Standard Edition).
JDBC is a specification that defines a complete set of interfaces for accessing an underlying database from a mobile device.
The term "network programming" refers to the process of building programs that run on several devices (computers) that are all connected via a network.
The J2SE APIs' java.net package contains a collection of classes and interfaces that provide low-level communication details, allowing you to focus on writing programs that solve the problem at hand.
Ava networking is a concept that entails connecting two or more computing units in order to share resources.
Java socket programming allows data to be shared between multiple computing machines.
Two protocols are supported by the java.net package:
TCP - The Transmission Control Protocol ensures that the sender and receiver communicate in a secure manner. TCP is used in conjunction with TCP/IP, which stands for Transmission Control Protocol/Internet Protocol.
UDP - By allowing packets of data to be exchanged across two or more nodes, the User Datagram Protocol provides a connectionless protocol service.
Advantages
● Resources are shared.
● Software administration should be centralized.
Terminology
The following are some of the most commonly used Java networking terms:
● IP Address
● Protocol
● Port Number
● MAC Address
● Connection-oriented and connectionless protocol
● Socket
IP address
An IP address, such as 192.168.0.1, is a unique number allocated to a network node. It is made up of octets with values ranging from 0 to 255.
It's an address that can be altered logically.
Protocol
A protocol is a collection of rules that must be followed in order to communicate. Consider the following scenario:
● TCP
● FTP
● Telnet
● SMTP
● POP etc.
Port number
The port number is used to distinguish between various apps. It serves as an interface for apps to communicate with one another.
For communication between two programs, the port number is related with the IP address.
MAC address
The MAC (Media Access Control) address is a network interface card's unique identity (Network Interface Controller). Multiple NICs can be found on a network node, but each has its own MAC address.
A MAC address of 00:0d:83::b1:c0:8e, for example, might be assigned to an Ethernet card.
Connection-oriented and connectionless protocol
The receiver sends acknowledgement in a connection-oriented protocol. As a result, it is dependable yet slow. TCP is an example of a connection-oriented protocol.
The receiver, on the other hand, does not send acknowledgement in a connectionless protocol. As a result, it is not only unreliable but also inefficient. UDP is an example of a connectionless protocol.
Socket
A socket is a communication endpoint for two-way communication.
Key takeaway
The term "network programming" refers to the process of building programs that run on several devices (computers) that are all connected via a network.
For communication between programs running on various JREs, Java Socket programming is utilized.
Connection-oriented and connectionless Java Socket programming are both possible.
Connection-oriented socket programming is done with the Socket and Server Socket classes, whereas connection-less socket programming is done with the Datagram Socket and Datagram Packet classes.
In socket programming, the client must know two things:
● IP Address of Server, and
● Port number.
We're going to do one-way client-server connection here. In this application, the client delivers a message to the server, which is read and printed by the server. Socket and Server Socket are the two classes utilized in this example. Client and server communication is handled by the Socket class. We can read and write messages in this class. On the server side, the Server Socket class is utilized. Until the client is connected, the accept() function of the Server Socket class disables the console. It returns a Socket instance to the server after a successful client connection.
Fig 9: Socket API
Socket class
A socket is just a communication endpoint between two machines. To create a socket, utilize the Socket class.
Methods
Methods | Description |
1) public InputStream getInputStream() | This function returns the InputStream associated with this socket. |
2) public OutputStream getOutputStream() | The OutputStream associated with this connection is returned. |
3) public synchronized void close() | Closes this socket |
Server socket class
A server socket can be created using the ServerSocket class. The purpose of this object is to communicate with the clients.
Methods
Methods | Description |
1) public Socket accept() | The socket is returned, and a connection between the server and the client is established. |
2) public synchronized void close() | Closes the server socket. |
Socket client example
The following is a list of resources. GreetingClient is a client software that uses a socket to connect to a server and sends a greeting before waiting for a response.
// File Name GreetingClient.java
Import java.net.*;
Import java.io.*;
Public class GreetingClient {
Public static void main(String [] args) {
String serverName = args[0];
Int port = Integer.parseInt(args[1]);
Try {
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
Out.writeUTF("Hello from " + client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
Client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Socket server example
The GreetingServer program shows how to use the Socket class to listen for clients on a port supplied by a command-line input.
// File Name GreetingServer.java
Import java.net.*;
Import java.io.*;
Public class GreetingServer extends Thread {
Private ServerSocket serverSocket;
Public GreetingServer(int port) throws IOException {
ServerSocket = new ServerSocket(port);
ServerSocket.setSoTimeout(10000);
}
Public void run() {
While(true) {
Try {
System.out.println("Waiting for client on port " +
ServerSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
Out.writeUTF("Thank you for connecting to " + server.getLocalSocketAddress()
+ "\nGoodbye!");
Server.close();
} catch (SocketTimeoutException s) {
System.out.println("Socket timed out!");
Break;
} catch (IOException e) {
e.printStackTrace();
Break;
}
}
}
Public static void main(String [] args) {
Int port = Integer.parseInt(args[0]);
Try {
Thread t = new GreetingServer(port);
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
After compiling the client and server, run the server as follows:
$ java GreetingServer 6066
Waiting for client on port 6066...
Take a look at the client program as follows:
Output
$ java GreetingClient localhost 6066
Connecting to localhost on port 6066
Just connected to localhost/127.0.0.1:6066
Server says Thank you for connecting to /127.0.0.1:6066
Goodbye!
Key takeaway
TCP sockets provide a means of communication between two machines. On its end of the conversation, a client application builds a socket and attempts to connect it to a server.
At the end of the conversation, the server produces a socket object when the connection is established. Writing to and reading from the socket allows the client and server to communicate.
TCP/IP is supported by Java by extending the existing established stream I/O interface presented and by adding the characteristics needed to create I/O objects across the network. The TCP and UDP protocol families are both supported by Java. TCP is a network protocol that allows for dependable stream-based I/O. UDP enables a point-to-point datagram-oriented approach, which is simpler and thus faster. The following are the classes found in the java.net package:
Authenticator
CacheRequest
CacheResponse
ContentHandler
CookieHandler
CookieManager
DatagramPacket
DatagramSocket
DatagramSocketImpl
HttpCookie
HttpURLConnection
IDN
Inet4Address
Inet6Address
InetAddress
InetSocketAddress
InterfaceAddress
JarURLConnection
MulticastSocket
NetPermission
NetworkInterface
PasswordAuthentication
Proxy
ProxySelector
ResponseCache
SecureCacheResponse
ServerSocket
Socket
SocketAddress
SocketImpl
SocketPermission
StandardSocketOption
URI
URL
URLClassLoader
URLConnection
URLDecoder
URLEncoder
URLPermission (Added by JDK 8.)
URLStreamHandler
The java.net package’s interfaces are listed here:
● ContentHandlerFactory
● CookiePolicy
● CookieStore
● DatagramSocketImplFactoy
● FileNameMap
● ProtocolFamily
● SocketImplFactory
● SocketOption
● SocketOptions
● URLStreamHandlerFactory
We'll look at the main networking classes and present some examples that apply to them in the sections that follow. You'll be able to quickly explore the others on your own once you've mastered these essential networking classes.
Key takeaway
TCP/IP is supported by Java by extending the existing established stream I/O interface presented and by adding the characteristics needed to create I/O objects across the network.
TCP/IP sockets are used to provide secure, bidirectional, permanent, point-to-point, stream-based connections between Internet hosts. A socket connects Java's I/O system to other applications running on the local machine or on any other machine connected to the Internet.
In Java, there are two types of TCP sockets. The first is for servers, while the second is for clients. The Server Socket class is intended to act as a "listener," meaning it will wait for clients to connect before proceeding. As a result, Server Socket is just for servers. Clients use the Socket class. Its purpose is to establish connections to server sockets and commence protocol exchanges. Client sockets are explored since they are the most widely used by Java applications.
When you create a Socket object, you're automatically establishing a connection between the client and the server. There are no explicit methods or constructors that expose the intricacies of making that connection. The following are two constructors for creating client sockets:
Socket has a number of instance methods. For example, the address and port information associated with a Socket can be inspected at any moment using the following methods:
InetAddress getInetAddress( ) - The Inet Address linked with the Socket object is returned. If the socket is not connected, it returns null.
Int getPort( ) - The remote port that the invoking Socket object is connected to is returned. If the socket is not connected, it returns 0.
Int getLocalPort( ) - The local port that the calling Socket object is attached to is returned. If the socket is not bound, it returns –1.
The getInputStream( ) and getOuptutStream( ) methods can be used to access the input and output streams associated with a Socket, as seen above. If the socket has been invalidated due to a loss of connection, each can produce an IO Exception.
InputStream getInputStream( ) throws IOException - The Input Stream connected with the initiating socket is returned.
OutputStream getOutputStream( )throws IOException - The Output Stream connected with the calling socket is returned.
Connect(), which allows you to specify a new connection; isConnected(), which returns true if the socket is connected to a server; isBound(), which returns true if the socket is bound to an address; and isClosed(), which returns true if the socket is closed are among the other methods available. Call close to close a socket ( ). When you close a socket, you're also closing the socket's I/O streams. Socket now implements AutoCloseable, which means you can manage a socket using a try-with-resources block starting with JDK 7.
A simple Socket example can be found in the following program. It establishes a connection to the InterNIC server's "whois" port (port 43), transmits the command-line input down the socket, and outputs the data received. InterNIC will attempt to check up the argument as a registered Internet domain name and return the site's IP address and contact details.
// Demonstrate Sockets.
Import java.net.*; import java.io.*;
Class Whois {
Public static void main(String args[]) throws Exception { int c;
Create a socket connected to internic.net, port 43. Socket s = new Socket("whois.internic.net", 43);
Obtain input and output streams.
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
// Construct a request string.
String str = (args.length == 0 ? "MHProfessional.com" : args[0]) + "\n";
// Convert to bytes.
Byte buf[] = str.getBytes();
Send request. Out.write(buf);
//Read and display response.
While ((c = in.read()) != -1) { System.out.print((char) c);
}
s.close();
}
}
Key takeaway
TCP/IP sockets are used to provide secure, bidirectional, permanent, point-to-point, stream-based connections between Internet hosts. A socket connects Java's I/O system to other applications running on the local machine or on any other machine connected to the Internet.
The following example establishes a connection to the InterNIC server's "whois" port, transmits the command-line parameter down the socket, and prints the data returned. InterNIC will attempt to check up the argument as a registered Internet domain name, and then return the site's IP address and contact details.
//Demonstrate Sockets.
Import java.net.*;
Import java.io.*;
Class Whois {
Public static void main(String args[]) throws Exception {
Int c;
Socket s = new Socket("internic.net", 43);
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
String str = (args.length == 0 ? "starwave-dom" : args[0]) +
"\\n";
Byte buf[] = str.getBytes();
Out.write(buf);
While ((c = in.read()) != -1) {
System.out.print((char) c);
}
s.close();
}
}
Because the modern Internet does not employ earlier protocols like whois, finger, or FTP, the preceding example was quite obscure. It's all about the World Wide Web, or WWW. The World Wide Web is a loose collection of higher-level protocols and file formats, all of which are unified in a web browser. Tim Berners-Lee invented a scalable technique to locate all of the Net's resources, which is one of the most significant components of the Web. It becomes a really powerful paradigm once you can dependably name anything and anything. This is exactly what the Uniform Resource Locator (URL) does.
The URL is a somewhat comprehensible convention for identifying or addressing information on the Internet.
The URL class serves as a portal to any online resource. A Class URL is a pointer to a "resource" on the World Wide Web that is represented by a Uniform Resource Locator. A resource can relate to a basic file or directory, or a more complex object, such as a database query or a search engine query.
What is a URL?
As many of you are probably aware, a Uniform Resource Locator (URL) is a string of text that identifies all resources on the Internet by informing us their address, how to communicate with them, and how to receive information from them.
The following is a basic URL:
Http://www.google.com/what-is-java/
Components of a URL:
A URL can take several different forms. The most common system, however, is a three-component system.
Protocol: HTTP is the protocol here
Hostname: Name of the machine on which the resource lives.
File Name: The path name to the file on the machine.
Port Number: Port number to which to connect (typically optional).
Key takeaway
Because the modern Internet does not employ earlier protocols like whois, finger, or FTP, the preceding example was quite obscure. It's all about the World Wide Web, or WWW.
The World Wide Web is a loose collection of higher-level protocols and file formats, all of which are unified in a web browser.
URL Connection is a general-purpose class for accessing a remote resource's properties. You can use URL Connection to verify the characteristics of a remote item before moving it locally once you've established a connection to a remote server. These properties are only relevant for URL objects that use the HTTP protocol, as they are provided by the HTTP protocol specification.
OpenConnection() returns a java.net object.
URL Connection is an abstract class that has several subclasses that represent different sorts of URL connections.
● The openConnection() function returns a Http URL Connection object when you connect to a URL that uses the HTTP protocol.
● The openConnection() method returns a Jar URL Connection object if you connect to a URL that represents a JAR file, for example.
There are numerous methods defined in URL Connection. Here's an example:
Sr.No. | Method & Description |
1 | Object getContent() The contents of this URL connection are returned. |
2 | Object getContent(Class[] classes) The contents of this URL connection are returned. |
3 | String getContentEncoding() The value of the content-encoding header field is returned. |
4 | Int getContentLength() The value of the content-length header field is returned. |
5 | String getContentType() The value of the content-type header field is returned. |
6 | Int getLastModified() The value of the last-modified header field is returned. |
7 | Long getExpiration() The value of the expired header field is returned. |
8 | Long getIfModifiedSince() The value of the ifModifiedSince field of this object is returned. |
9 | Public void setDoInput(boolean input) The connection will be used for input if true is passed in. Because clients normally read from a URLConnection, the default value is true. |
10 | Public void setDoOutput(boolean output) The connection will be used for output if true is sent in. Because many types of URLs do not support being written to, the default value is false. |
11 | Public InputStream getInputStream() throws IOException Returns the URL connection's input stream for reading from the resource. |
12 | Public OutputStream getOutputStream() throws IOException Returns the URL connection's output stream for writing to the resource. |
13 | Public URL getURL() This method returns the URL to which this URLConnection object is linked. |
Example
The URLConnectionDemo software connects to a URL that is entered on the command line.
The connection is cast to HttpURLConnection if the URL represents an HTTP resource, and the data in the resource is read one line at a time.
// File Name : URLConnDemo.java
Import java.net.*;
Import java.io.*;
Public class URLConnDemo {
Public static void main(String [] args) {
Try {
URL url = new URL("https://www.amrood.com");
URLConnection urlConnection = url.openConnection();
HttpURLConnection connection = null;
If(urlConnection instanceof HttpURLConnection) {
Connection = (HttpURLConnection) urlConnection;
}else {
System.out.println("Please enter an HTTP URL.");
Return;
}
BufferedReader in = new BufferedReader(
New InputStreamReader(connection.getInputStream()));
String urlString = "";
String current;
While((current = in.readLine()) != null) {
UrlString += current;
}
System.out.println(urlString);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Output
$ java URLConnDemo
.....a complete HTML content of home page of amrood.com.....
Key takeaway
URL Connection is a general-purpose class for accessing a remote resource's properties. You can use URL Connection to verify the characteristics of a remote item before moving it locally once you've established a connection to a remote server.
For server applications, Java has a distinct socket class that must be used. The Server Socket class is used to develop servers that listen on published ports for connections from local or remote client programs. Server Sockets are not the same as regular Sockets. When you build a Server Socket, it will inform the system that it is interested in receiving client connections.
Server Socket's constructors reflect the port number on which you want to accept connections and, optionally, the length of the queue for that port. The queue length tells the system how many pending client connections it may keep before just rejecting them. The default setting is 50. Under certain circumstances, the constructors may throw an IO Exception.
Here are three of its constructors:
ServerSocket(int port) throws IOException | Creates a server socket with a cube length of 50 on the specified code.
|
ServerSocket(int port, int maxQueue) throws IOException | Create a server socket with a maximum queue length of maxQueue on the specified port. |
ServerSocket(int port, int maxQueue, InetAddress localAddress) throws IOException | Creates a server socket with a maximum queue length of MaxQueue on the specified port. LocalAddress provides the IP address to which this socket binds on a multihomed host. |
Accept() is a blocking function on ServerSocket that waits for a client to commence communication before returning with a standard Socket that may be used to communicate with the client.
Key takeaway
For server applications, Java has a distinct socket class that must be used.
The Server Socket class is used to develop servers that listen on published ports for connections from local or remote client programs.
Server Sockets are not the same as regular Sockets.
When you build a Server Socket, it will inform the system that it is interested in receiving client connections.
References:
- Introduction to Java Programming: Liang, Pearson Education, 7th Edition.
- Balguruswamy, Programming with Java, TMH.
- Programming with Java: Bhave & Patekar, Person Eduction.
- Java Programming Advanced Topics: Wigglesworth, Cengage Learning.
- Https://www.javatpoint.com/
- Https://www.tutorialspoint.com/java/java_networking.htm
- Https://www.brainkart.com/article/TCP-IP-Server-Sockets---Java-Networking_10620/