UNIT-5 Java String Handling
UNIT-5 Java String Handling
It is probably the most commonly used class in java library. In java, every string that we create is actually an
object of type String. One important thing to notice about string object is that string objects
are immutable that means once a string object is created it cannot be changed.
The Java String class implements Serializable, Comparable and CharSequence interface that we have
represented using the below image.
In Java, CharSequence Interface is used for representing a sequence of characters. CharSequence interface
is implemented by String, StringBuffer and StringBuilder classes. This three classes can be used for creating
strings in java.
Class string:
Strings, which are widely used in Java programming, are a sequence of characters. In Java programming
language, strings are treated as objects.
The Java platform provides the String class to create and manipulate strings.
Creating Strings
The most direct way to create a string is to write −
String greeting = "Hello world!";
Whenever it encounters a string literal in your code, the compiler creates a String object with its value in
this case, "Hello world!'.
As with any other object, you can create String objects by using the new keyword and a constructor. The
String class has 11 constructors that allow you to provide the initial value of the string using different
sources, such as an array of characters.
Example
public class StringDemo {
Output
hello.
Note − The String class is immutable, so that once it is created a String object cannot be changed. If there
is a necessity to make a lot of modifications to Strings of characters, then you should use String Buffer &
String Builder Classes.
String Length
Methods used to obtain information about an object are known as accessor methods. One accessor method
that you can use with strings is the length() method, which returns the number of characters contained in
the string object.
The following program is an example of length(), method String class.
Example
public class StringDemo {
Output
String Length is : 17
Concatenating Strings
The String class includes a method for concatenating two strings −
string1.concat(string2);
This returns a new string that is string1 with string2 added to it at the end. You can also use the concat()
method with string literals, as in −
"My name is ".concat("Zara");
Strings are more commonly concatenated with the + operator, as in −
"Hello," + " world" + "!"
which results in −
"Hello, world!"
Let us look at the following example −
Example
public class StringDemo {
Output
Dot saw I was Tod
Example
System.out.printf("The value of the float variable is " +
"%f, while the value of the integer " +
"variable is %d, and the string " +
"is %s", floatVar, intVar, stringVar);
You can write −
String fs;
fs = String.format("The value of the float variable is " +
"%f, while the value of the integer " +
"variable is %d, and the string " +
"is %s", floatVar, intVar, stringVar);
System.out.println(fs);
String Methods
Here is the list of methods supported by String class –
2 int compareTo(Object o)
Returns true if and only if this String represents the same sequence of characters as the
specified StringBuffer.
Returns a String that represents the character sequence in the array specified.
Returns a String that represents the character sequence in the array specified.
12 byte[] getBytes()
Encodes this String into a sequence of bytes using the platform's default charset, storing
the result into a new byte array.
13 byte[] getBytes(String charsetName)
Encodes this String into a sequence of bytes using the named charset, storing the result
into a new byte array.
Copies characters from this string into the destination character array.
15 int hashCode()
Returns the index within this string of the first occurrence of the specified character.
Returns the index within this string of the first occurrence of the specified character,
starting the search at the specified index.
Returns the index within this string of the first occurrence of the specified substring.
Returns the index within this string of the first occurrence of the specified substring,
starting at the specified index.
20 String intern()
Returns the index within this string of the last occurrence of the specified character.
Returns the index within this string of the last occurrence of the specified character,
searching backward starting at the specified index.
23 int lastIndexOf(String str)
Returns the index within this string of the rightmost occurrence of the specified substring.
Returns the index within this string of the last occurrence of the specified substring,
searching backward starting at the specified index.
25 int length()
Tells whether or not this string matches the given regular expression.
27 boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
Returns a new string resulting from replacing all occurrences of oldChar in this string
with newChar.
Replaces each substring of this string that matches the given regular expression with the
given replacement.
Replaces the first substring of this string that matches the given regular expression with
the given replacement.
Tests if this string starts with the specified prefix beginning a specified index.
39 char[] toCharArray()
40 String toLowerCase()
Converts all of the characters in this String to lower case using the rules of the default
locale.
Converts all of the characters in this String to lower case using the rules of the given
Locale.
42 String toString()
Converts all of the characters in this String to upper case using the rules of the default
locale.
Converts all of the characters in this String to upper case using the rules of the given
Locale.
45 String trim()
Returns a copy of the string, with leading and trailing whitespace omitted.
Character Extraction:
The String class provides a number of ways in which characters can be extracted from a String object.
Several are examined here. Although the characters that comprise a string within a String object cannot be
indexed as if they were a character array, many of the String methods employ an index (or offset) into the
string for their operation. Like arrays, the string indexes begin at zero.
charAt( ):
To extract a single character from a String, you can refer directly to an individual character via the charAt(
) method. It has this general form:
char charAt(int where)
Here, where is the index of the character that you want to obtain. The value of where must be nonnegative
and specify a location within the string. charAt( ) returns the character at the specified location. For
example,
char ch;
ch = "abc".charAt(1);
assigns the value b to ch.
getChars( ):
If you need to extract more than one character at a time, you can use the getChars( ) method. It has this
general form:
void getChars(int sourceStart, int sourceEnd, char target[ ], int targetStart)
The following program demonstrates getChars( ):
class 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);
}
}
getBytes( ):
There is an alternative to getChars( ) that stores the characters in an array of bytes. This method is
called getBytes( ), and it uses the default character-to-byte conversions provided by the platform. Here is its
simplest form:
byte[ ] getBytes( )
Other forms of getBytes( ) are also available. getBytes( ) is most useful when you are exporting
a String value into an environment that does not support 16-bit Unicode characters. For example, most
Internet protocols and text file formats use 8-bit ASCII for all text interchange.
toCharArray( ):
If you want to convert all the characters in a String object into a character array, the easiest way is to
call toCharArray( ). It returns an array of characters for the entire string. It has this general form:
char[ ] toCharArray( )
This function is provided as a convenience, since it is possible to use getChars( ) to achieve the same result.
String Comparison:
The String class includes a number of methods that compare strings or substrings within strings. Several are
examined here.
equals( ) and equalsIgnoreCase( )
To compare two strings for equality, use equals( ). It has this general form: boolean equals(Object str)
Here, str is the String object being compared with the invoking String object. It returns true if the strings
contain the same characters in the same order, and false otherwise. The comparison is case-sensitive.
To perform a comparison that ignores case differences, call equalsIgnoreCase( ). When it compares two
strings, it considers A-Z to be the same as a-z. It has this general form:
boolean equalsIgnoreCase(String str)
Here, str is the String object being compared with the invoking String object. It, too, returns true if the
strings contain the same characters in the same order, and false otherwise.
Here is an example that demonstrates equals( ) and equalsIgnoreCase( ):
// Demonstrate equals() and equalsIgnoreCase().
class equalsDemo {
String s = "Now is the time for all good men " + "to come to the aid of their country."; System.out.println(s);
System.out.println("indexOf(t) = " +s.indexOf('t')); System.out.println("lastIndexOf(t) = "
+ s.lastIndexOf('t')); System.out.println("indexOf(the) = " +s.indexOf("the"));
System.out.println("lastIndexOf(the) = " +s.lastIndexOf("the")); System.out.println("indexOf(t, 10) = "
+s.indexOf('t', 10)); System.out.println("lastIndexOf(t, 60) = " +s.lastIndexOf('t', 60));
System.out.println("indexOf(the, 10) = " +s.indexOf("the", 10));
System.out.println("lastIndexOf(the, 60) = " +s.lastIndexOf("the", 60));
}
}
Here is the output of this program:
Now is the time for all good men to come to the aid of their country. indexOf(t) = 7
lastIndexOf(t) = 65
indexOf(the) = 7
lastIndexOf(the) = 55
indexOf(t, 10) = 11
lastIndexOf(t, 60) = 55
indexOf(the, 10) = 44
lastIndexOf(the, 60) = 55
Modifying a String
Because String objects are immutable, whenever you want to modify a String, you must either copy it into
a StringBuffer or StringBuilder, or use a String method that constructs a new copy of the string with your
modifications complete. A sampling of these methods are described here.
substring( )
You can extract a substring using substring( ). It has two forms. The first is String substring(int startIndex)
Here, startIndex specifies the index at which the substring will begin. This form returns a copy of the
substring that begins at startIndex and runs to the end of the invoking string.
The second form of substring( ) allows you to specify both the beginning and ending index of the substring:
String substring(int startIndex, int endIndex)
Here, startIndex specifies the beginning index, and endIndex specifies the stopping point. The string
returned contains all the characters from the beginning index, up to, but not including, the ending index.
The following program uses substring( ) 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);
}
}
The output from this program is shown here:
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( )
You can concatenate two strings using concat( ), shown here: String concat(String str)
This method creates a new object that contains the invoking string with the contents of str appended to the
end. concat( ) performs the same function as +. For example,
String s1 = "one";
String s2 = s1.concat("two");
puts the string "onetwo" into s2. It generates the same result as the following sequence:
String s1 = "one";
String s2 = s1 + "two";
replace( )
The replace( ) method has two forms. The first replaces all occurrences of one character in the invoking
string with another character. It has the following general form:
String replace(char original, char replacement)
Here, original specifies the character to be replaced by the character specified by replacement. The resulting
string is returned. For example,
String s = "Hello".replace('l', 'w');
puts the string "Hewwo" into s.
The second form of replace( ) replaces one character sequence with another. It has this general form:
String replace(CharSequence original, CharSequence replacement)
trim( )
The trim( ) method returns a copy of the invoking string from which any leading and trailing whitespace
has been removed. It has this general form:
String trim( ) Here is an example:
String s = " Hello World ".trim();
This puts the string "Hello World" into s.
The trim( ) method is quite useful when you process user commands. For example, the following program
prompts the user for the name of a state and then displays that state’s capital. It uses trim( ) to remove any
leading or trailing whitespace that may have inadvertently been entered by the user.
// Using trim() to process commands.
import java.io.*;
class UseTrim {
public static void main(String args[]) throws IOException
{
static String valueOf(double num) static String valueOf(long num) static String valueOf(Object ob) static
String valueOf(char chars[ ])
valueOf( ) is called when a string representation of some other type of data is needed—for example, during
concatenation operations. You can call this method directly with any data type and get a
reasonable String representation. All of the simple types are converted to their
common String representation. Any object that you pass to valueOf( ) will return the result of a call to the
object’s toString( ) method. In fact, you could just call toString( ) directly and get the same result.
For most arrays, valueOf( ) returns a rather cryptic string, which indicates that it is an array of some type.
For arrays of char, however, a String object is created that contains the characters in the char array. There
is a special version of valueOf( ) that allows you to specify a subset of a char array. It has this general
form:
static String valueOf(char chars[ ], int startIndex, int numChars)
Here, chars is the array that holds the characters, startIndex is the index into the array of characters at which
the desired substring begins, and numChars specifies the length of the substring.
StringBuffer
StringBuffer supports a modifiable string. As you know, String represents fixed-length, immutable
character sequences. In contrast, StringBuffer represents growable and writable character
sequences. StringBuffer may have characters and substrings inserted in the middle or appended to the
end. StringBuffer will automatically grow to make room for such additions and often has more characters
preallocated than are actually needed, to allow room for growth.
StringBuffer Constructors
StringBuffer defines these four constructors:
StringBuffer( ) StringBuffer(int size) StringBuffer(String str)
StringBuffer(CharSequence chars)
The default constructor (the one with no parameters) reserves room for 16 characters without reallocation.
The second version accepts an integer argument that explicitly sets the size of the buffer. The third version
accepts a String argument that sets the initial contents of the StringBuffer object and reserves room for 16
more characters without reallocation. StringBuffer allocates room for 16 additional characters when no
specific buffer length is requested, because reallocation is a costly process in terms of time. Also, frequent
reallocations can fragment memory. By allocating room for a few extra characters, StringBuffer reduces
the number of reallocations that take place. The fourth constructor creates an object that contains the
character sequence contained in chars and reserves room for 16 more characters.
length( ) and capacity( )
The current length of a StringBuffer can be found via the length( ) method, while the total allocated
capacity can be found through the capacity( ) method. They have the following general forms:
int length( ) int capacity( )
Here is an example:
// StringBuffer length vs. capacity.
class StringBufferDemo {
public static void main(String args[]) {
StringBuffer sb = new StringBuffer("Hello");
System.out.println("buffer = " + sb);
System.out.println("length = " + sb.length()); System.out.println("capacity = " + sb.capacity());
}
}
Here is the output of this program, which shows how StringBuffer reserves extra space for additional
manipulations:
buffer = Hello length = 5 capacity = 21
Since sb is initialized with the string "Hello" when it is created, its length is 5. Its capacity is 21 because
room for 16 additional characters is automatically added.
ensureCapacity( )
If you want to preallocate room for a certain number of characters after a StringBuffer has been
constructed, you can use ensureCapacity( ) to set the size of the buffer. This is useful if you know in
advance that you will be appending a large number of small strings to a
StringBuffer. ensureCapacity( ) has this general form:
void ensureCapacity(int minCapacity)
Here, minCapacity specifies the minimum size of the buffer. (A buffer larger than minCapacity may be
allocated for reasons of efficiency.)
setLength( )
To set the length of the string within a StringBuffer object, use setLength( ). Its general form is shown
here:
void setLength(int len)
Here, len specifies the length of the string. This value must be nonnegative.
When you increase the size of the string, null characters are added to the end. If you call setLength( ) with a
value less than the current value returned by length( ), then the characters stored beyond the new length will
be lost. The setCharAtDemo sample program in the following section uses setLength( ) to shorten
a StringBuffer.
charAt( ) and setCharAt( )
The value of a single character can be obtained from a StringBuffer via the charAt( ) method. You can set
the value of a character within a StringBuffer using setCharAt( ). Their general forms are shown here:
char charAt(int where)
void setCharAt(int where, char ch)
For charAt( ), where specifies the index of the character being obtained. For setCharAt( ), where specifies
the index of the character being set, and ch specifies the new value of that character. For both
methods, where must be nonnegative and must not specify a location beyond the end of the string.
The following example demonstrates charAt( ) and setCharAt( ):
// Demonstrate charAt() and setCharAt().
class setCharAtDemo {
public static void main(String args[]) {
StringBuffer sb = new StringBuffer("Hello"); System.out.println("buffer before = " + sb);
The string representation of each parameter is obtained, often by calling String.valueOf( ). The result is
appended to the current StringBuffer object. The buffer itself is returned by each version of append( ).
This allows subsequent calls to be chained together, as shown in the following example:
// Demonstrate append().
class appendDemo {
public static void main(String args[]) {
String s;
int a = 42;
StringBuffer sb = new StringBuffer(40);
s = sb.append("a = ").append(a).append("!").toString(); System.out.println(s);
}
}
The output of this example is shown here:
a = 42!
insert( )
The insert( ) method inserts one string into another. It is overloaded to accept values of all the primitive
types, plus Strings, Objects, and CharSequences. Like append( ), it obtains the string representation of the
value it is called with. This string is then inserted into the invoking StringBuffer object. These are a few of
its forms:
StringBuffer insert(int index, String str) StringBuffer insert(int index, char ch) StringBuffer insert(int index,
Object obj)
Here, index specifies the index at which point the string will be inserted into the invoking
StringBuffer object.
The following sample program inserts "like" between "I" and "Java":
// Demonstrate insert().
class insertDemo {
public static void main(String args[]) { StringBuffer sb = new StringBuffer("I Java!");
sb.insert(2, "like "); System.out.println(sb);
}
}
The substring being replaced is specified by the indexes startIndex and endIndex. Thus, the substring
at startIndex through endIndex–1 is replaced. The replacement string is passed in str. The
resulting StringBuffer object is returned.
The following program demonstrates replace( ):
// Demonstrate replace()
class replaceDemo {
public static void main(String args[]) {
StringBuffer sb = new StringBuffer("This is a test.");
sb.replace(5, 7, "was"); System.out.println("After replace: " + sb);
}
}
However, there are two distinct types of multitasking: process based and thread-based.
It is important to understand the difference between the two. For most readers, process-based
multitasking is the more familiar form. A process is, in essence, a program that is executing.
Thus, process-based multitasking is the feature that allows your computer to run two or more
programs concurrently. For example, process-based multitasking enables you to run the Java
compiler at the same time that you are using a text editor. In process based multitasking, a
program is the smallest unit of code that can be dispatched by the scheduler.
Runnable State: A runnable state means that a thread is ready for execution and waiting for the
availability of the processor. That is the thread has joined the queue of the threads for execution.
If all the threads have equal priority, then they are given time slots for execution in the round
rabin fashion, first-come-first-serve manner. The thread that relinquishes the control will join the
queue at the end and again waits for its turn. This is known as time slicing.
Running state: Running state means that the processor has given its time to the thread for it
execution. The thread runs until it relinquishes the control or it is preempted by the other higher
priority thread. As shown in the Fig 1. a running thread can be preempted using the suspen(), or
wait(), or sleep() methods.
Blocked state: A thread is said to be in the blocked state when it is prevented from entering into
runnable state and subsequently the running state.
Dead state: Every thread has a life cycle. A running thread ends its life when it has completed
execution. It is a natural death. However we also can kill the thread by sending the stop()
message to it at any time.
2. public void start(): starts the execution of the thread.JVM calls the run() methodon the thread.
3. public void sleep(long miliseconds): Causes the currently executing thread tosleep (temporarily cease
execution) for the specified number of milliseconds.
5. public void join(long miliseconds): waits for a thread to die for the specifiedmiliseconds.
14. public void yield(): causes the currently executing thread object to temporarilypause and allow other
threads to execute.
15. public void suspend(): is used to suspend the thread(depricated).
19. public void setDaemon(boolean b): marks the thread as daemon or user thread.
21. public boolean isInterrupted(): tests if the thread has been interrupted.
22. public static boolean interrupted(): tests if the current thread has beeninterrupted.
Multithreading in Java
Every program that we have been writing has at least one thread, that is, the "main" thread.
Whenever a program starts executing, the JVM is responsible for creating the main thread and
calling "main()" method. Along with this main thread, some other threads are also running to
carryout the tasks such as "finalization" and "garbage collection". The thread can either die
naturally or be forced to die.
Thread dies naturally when it exits from the "run()" method.
Thread can be forced to die by calling "interrupt()" method.
java.lang.Thread package
Creation of Thread in java is very simple task. There is a class called "Thread", which belongs to
the "java.lang.Thread" package. This package contains one interface also called "Runnable".
Both these contain a common method called "run()" which is the heart of the thread. The run()
method would have the following syntax:
Syntax:
public void run()
{
//statement for implementing the thread.
Thread
} Constructors:
Every java program has a thread called "main" thread. When the program execution
starts, the JVM creates "main" Thread and calls the "main()" method from within that thread.
Along with this JVM also creates other threads for the purpose of the Housekeeping task such as
"garbage" collection. The "main" thread Spawns the other Threads. These spawned threads are
called "Child Threads". The main thread is always is the last thread to finish execution. We, as
Programmer can also take control of the main thread, using the method "currentThread()". The
main thread can be controlled by this method. We can also change the name of the Thread using
the method "setName(String name)".
Example Program:
MainThread.java
class MainThread
{
public static void main(String args[])
{
Thread t=Thread.currentThread();
System.out.println("Name of the Thread is:"+t);
t.setName("KSR");
System.out.println("Name of the Thread is:"+t);
}
}
Creating the threads in the Java is simple. The threads can be implemented in the form of object that
contains a method "run()". The "run()" method is the heart and soul of any thread. It makes up the
entire body of the thread and is the only method in which the thread behavior can be implemented.
There are two ways to create thread.
1. Declare a class that extends the Thread class and override the run() method.
2. Declare a class that implements the Runnable interface which contains the run() method
Example program:
ThreadTest.java
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
}
System.out.println("Exit from Thread B");
for(int k=1;k<=5;k++)
class ThreadTest
a.start();
B b=new B();
b.start();
C c=new C();
c.start();
}
First Run Second Run
Note: If you observe here, first and second Runs produce different Results. This depends on the
Processor availability, speed of the processor, Scheduling algorithms and priority of the threads.
If you run this in two different systems they produce different outputs.
2. Creating the Thread using Runnable Interface
The Runnable interface contains the run() method that is required for implementing the
threads in our program. To do this we must perform the following steps:
I. Declare a class as implementing the Runnable interface
II. Implement the run() method
III. Create a Thread by defining an object that is instantiated from this "runnable" class as
the target of the thread
IV. Call the thread's start() method to run the thread.
Example program:
Runnable.java
Output: Threads A and B execution by running the above program two times. (You may see a different
sequence of Output, every time you run this program)
Answer: We may get one question, that is which way of creating thread is better. The Answer is, if you
want use others methods of the thread, then use Thread super class. If you are interested in only run()
method use Runnable interface.
Advantage of the Multithreading
It enables you to write very efficient programs that maximizes the CPU utilization and
reduces the idle time.
Most I/O devices such as network ports, disk drives or the keyboard are much slower
than CPU
A program will spend much of it time just send and receive the information to or from
the devices, which in turn wastes the CPU valuable time.
By using the multithreading, your program can perform another task during this idle
time.
For example, while one part of the program is sending a file over the internet, another
part can read the input from the keyboard, while other part can buffer the next block to
send.
It is possible to run two or more threads in multiprocessor or multi core systems
simultaneously.
This method returns the either "TRUE" or "FALSE" . It returns "TRUE" if the thread is alive,
returns "FALSE" otherwise.
While isAlive( ) is occasionally useful, the method that you will more commonly use to
wait for a thread to finish is called join( ). This method forces the currently running thread to
finish it task first.
This method also has another version as follow:
Public void run(milliseconds);
Here, time milliseconds are used to specify the deadline within which the thread has to
finish its task, context-switching is done to transfer control otherwise.
System.out.println("2*"+i+"="+(2*i)); System.out.println("2*"+i+"="+(2*i));
} }
} }
} }
class B implements Runnable class B implements Runnable
{ {
public void run() public void run()
{ {
for(int j=1;j<=10;j++) for(int j=1;j<=10;j++)
{ {
System.out.println("3*"+j+"="+(3*j)); System.out.println("3*"+j+"="+(3*j));
} }
} }
} }
class JoinTest class JoinTest
{ {
public static void main(String args[]) public static void main(String args[])
{ {
A a=new A(); A a=new A();
B b=new B(); B b=new B();
Thread t1=new Thread(a); Thread t1=new Thread(a); //providing runnable
//providing runnable object as argument object as argument
Thread t2=new Thread(b); Thread t2=new Thread(b);
t1.start(); Thread t3=new Thread(); //new thread t3 is created,
t2.start(); but note starte
} //calling isAlive() method
} System.out.println("Thread t3 is live :"+t3.isAlive());
t1.start();
//calling join() method
try
{
t1.join();
}
catch(InterruptedException ie)
{
}
t2.start();
System.out.println("Thread t2 is live :"+t2.isAlive());
}
}
Without join() output With join() output
Daemon Thread
Daemon thread is a low priority thread that runs in background to perform tasks such as
garbage collection.
Properties:
They cannot prevent the JVM from exiting when all the user threads finish their
execution.
JVM terminates itself when all user threads finish their execution
If JVM finds running daemon thread, it terminates the thread and after that shutdown
itself. JVM does not care whether Daemon thread is running or not.
It is an utmost low priority thread.
When is a user thread is finished, the JVM automatically terminates the Daemon
threads.
Methods:
1. void setDaemon(boolean status): This method is used to mark the current thread as
daemon thread or user thread. For example if I have a user thread tU then
tU.setDaemon(true) would make it Daemon thread. On the other hand if I have a Daemon
thread tD then by calling tD.setDaemon(false) would make it user thread.
Syntax:
2. boolean isDaemon():
This method is used to check that current is daemon. It returns true if the thread is
Daemon else it returns false.
Syntax:
for(int i=1;i<=1000;i++)
System.out.println("Daemon i="+i);
}
}
class UD extends Thread
{
public void run()
{
for (int j=1;j<=5;j++)
System.out.println("User j="+j);
}
}
class DTest
{
public static void main(String args[])
{
DT d=new DT();
d.setDaemon(true);
UD u=new UD();
d.start();
u.start();
}
}
Output:
Thread priorities are used by the thread scheduler to decide when and which thread
should be allowed to run. In theory, higher-priority threads get more CPU time than lower-
priority threads. In practice, the amount of CPU time that a thread gets often depends on several
factors besides its priority. (For example, how an operating system implements multitasking can
affect the relative availability of CPU time.) A higher-priority thread can also preempts (stops) a
lower-priority one. For instance, when a lower-priority thread is running and a higher-priority
thread resumes (from sleeping or waiting on I/O, for example), it will preempt the lower priority
thread.
To set a thread’s priority, use the setPriority( ) method, which is a member of Thread.
This is its general form:
final void setPriority(int level)
Here, level specifies the new priority setting for the calling thread. The value of level
must bewithin the range MIN_PRIORITY and MAX_PRIORITY. Currently, these values are
1 and10, respectively. To return a thread to default priority, specify NORM_PRIORITY, which
iscurrently 5. These priorities are defined as static final variables within Thread.
You can obtain the current priority setting by calling the getPriority( ) method of Thread,shown
here:
}
//setting the priorities to the thread using the setPriority() method
pt1.start();
pt2.start();
}
pt3.start();
Note: Of course, the
//getting the priority
exact output produced by this program depends on the speed of your CPU
and the number of other tasks running in the system. When this same program is run under a non
System.out.println("The
preemptive pt1 will
system, different results thread
be priority
obtained.is :"+pt1.getPriority());
}
Synchronization
When two or more threads need access to a shared resource, they need some way to
ensure that the resource will be used by only one thread at a time. The process by which this is
achieved is called synchronization.
Let us try to understand the problem without synchronization. Here, in the following
example two threads are accessing the same resource (object) to print the Table. The Table class
contains one method, printTable(int ), which actually prints the table. We are creating two
Threads, Thread1 and Thread2, which are using the same instance of the Table Resource
(object), to print the table. When one thread is using the resource, no other thread is allowed to
access the same resource Table to print the table.
In the above output it can be observed that when Thread1 is accessing the Table object,
Thread2 is not allowed to access it. Thread1 preempts the Thread2 from accessing the
printTable() method.
Note:
1. This way of communications between the threads competing for same resource is
called implicit communication.
2. This has one disadvantage due to polling. The polling wastes the CPU time. To save
the CPU time, it is preferred to go to the inter-thread communication.
Inter-Thread Communication
If two or more Threads are communicating with each other, it is called "inter thread"
communication. Using the synchronized method, two or more threads can communicate
indirectly. Through, synchronized method, each thread always competes for the resource. This
way of competing is called polling. The polling wastes the much of the CPU valuable time. The
better solution to this problem is, just notify other threads for the resource, when the current
thread has finished its task, meanwhile other threads will be doing some useful work. This is
explicit communication between the threads.
Java addresses this polling problem, using via wait(), notify(), and notifyAll() 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.
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 a thread that called wait( ) on the same object.
notifyAll( ) wakes up all the threads that called wait( ) on the same object. One of
the threads will be granted access.
{
int i = 0;
while(true)
{
q.put(i++);
}
}
}//end of Producer
class PCFixed
{
public static void main(String args[])
{
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-C to stop.");
}
}
Whenever we want stop a thread we can stop from running using "stop()" method of
thread class. It's general form will be as follows:
Thread.stop();
This method causes a thread to move from running to dead state. A thread will also
move to dead state automatically when it reaches the end of its method.
Blocking Thread
A thread can be temporarily suspended or blocked from entering into the runnable and
running state by using the following methods:
sleep() —blocked for specified time
suspend() --------- blocked until further orders
wait() --blocked until certain condition occurs
These methods cause the thread to go into the blocked state. The thread will return to the
runnable state when the specified time is elapsed in the case of sleep(), the resume() method is
invoked in the case of suspend(), and the notify() method is called in the case of wait().
Example program:
b.stop(); //stoping
}
catch(Exception e)
{
Thread Exceptions}
}
} Note that a call to the sleep() method is always enclosed in try/ catch block. This is
necessary because the sleep() method throws an exception, which should be caught. If we fail to
catch the exception the program will not compile. The join() method also generates an exception
called “InterruptedException”.
It’s general form will be as follows
try
{
Thread.sleep(1000);
}
cathc(Exception e)
{ --------
}
Deadlock
Deadlock in java is a part of multithreading. Deadlock can occur in a situation when a
thread is waiting for an object lock, that is acquired by another thread and second thread is
waiting for an object lock that is acquired by first thread. Since, both threads are waiting for each
other to release the lock, the condition is called deadlock.
Thread1 Thread2
Y
Example program:
public class TestDead
{
TestDead.java
public static void main(String[] args)
{
final String resource1 = "John Gardner";
final String resource2 = "James Gosling";
// t1 tries to lock resource1 then resource2
synchronized (resource2)
{
System.out.println("Thread 1: locked resource 2");
}
}
} //end of run()
}; //end of t1
(resource1)
{
System.out.println("Thread 2: locked resource 1");
}
}
}//end of run()
}; //end of t2
t1.start();
t2.start();
}
}
Output:
JDBC – Introduction
JDBC stands for Java Database Connectivity, which is a standard Java API for database-independent
connectivity between the Java programming language and a wide range of databases.
The JDBC library includes APIs for each of the tasks mentioned below that are commonly associated
with database usage.
Making a connection to a database.
Creating SQL or MySQL statements.
Executing SQL or MySQL queries in the database.
Viewing & Modifying the resulting records.
Fundamentally, JDBC is a specification that provides a complete set of interfaces that allows for portable
access to an underlying database. Java can be used to write different types of executables, such as −
Java Applications
Java Applets
Java Servlets
Java ServerPages (JSPs)
Enterprise JavaBeans (EJBs).
All of these different executables are able to use a JDBC driver to access a database, and take advantage
of the stored data.
JDBC provides the same capabilities as ODBC, allowing Java programs to contain database-independent
code.
Pre-Requisite
Before moving further, you need to have a good understanding of the following two subjects −
Core JAVA Programming
SQL or MySQL Database
JDBC Architecture
The JDBC API supports both two-tier and three-tier processing models for database access but in
general, JDBC Architecture consists of two layers −
JDBC API − This provides the application-to-JDBC Manager connection.
JDBC Driver API − This supports the JDBC Manager-to-Driver Connection.
The JDBC API uses a driver manager and database-specific drivers to provide transparent connectivity
to heterogeneous databases.
The JDBC driver manager ensures that the correct driver is used to access each data source. The driver
manager is capable of supporting multiple concurrent drivers connected to multiple heterogeneous
databases.
Following is the architectural diagram, which shows the location of the driver manager with respect to
the JDBC drivers and the Java application –
To use MySQL Connector/J with an application server such as GlassFish, Tomcat, or JBoss, read your vendor's
documentation for more information on how to configure third-party class libraries, as most application servers ignore
the CLASSPATH environment variable. For configuration examples for some J2EE application servers,
see Chapter 7, Connection Pooling with Connector/J, Section 8.2, “Configuring Load Balancing with Connector/J”,
and Section 8.4, “Advanced Load-balancing and Failover Configuration”. However, the authoritative source for JDBC
connection pool configuration information for your particular application server is the documentation for that application
server.
If you are developing servlets or JSPs, and your application server is J2EE-compliant, you can put the driver's .jar file in
the WEB-INF/lib subdirectory of your webapp, as this is a standard location for third party class libraries in J2EE web
applications.
You can also use the MysqlDataSource or MysqlConnectionPoolDataSource classes in
the com.mysql.jdbc.jdbc2.optional package, if your J2EE application server supports or requires them. Starting with
Connector/J 5.0.0, the javax.sql.XADataSource interface is implemented using
the com.mysql.jdbc.jdbc2.optional.MysqlXADataSource class, which supports XA distributed transactions when used in
combination with MySQL server version 5.0 and later.
The various MysqlDataSource classes support the following parameters (through standard set mutators):
user
password
serverName (see the previous section about failover hosts)
databaseName
port
You automatically get both JDBC packages java.sql and javax.sql, when you install J2SE Development
Kit.
Install Database
The most important thing you will need, of course is an actual running database with a table that you can
query and modify.
Install a database that is most suitable for you. You can have plenty of choices and most common are −
MySQL DB − MySQL is an open source database. You can download it from MySQL Official
Site. We recommend downloading the full Windows installation.
In addition, download and install MySQL Administrator as well as MySQL Query
Browser. These are GUI based tools that will make your development much easier.
Finally, download and unzip MySQL Connector/J (the MySQL JDBC driver) in a convenient
directory. For the purpose of this tutorial we will assume that you have installed the driver at
C:\Program Files\MySQL\mysql-connector-java-5.1.8.
Accordingly, set CLASSPATH variable to C:\Program Files\MySQL\mysql-connector-java-
5.1.8\mysql-connector-java-5.1.8-bin.jar. Your driver version may vary based on your
installation.
Create Database
To create the TUTORIALSPOINT database, use the following steps −
Step 1
Open a Command Prompt and change to the installation directory as follows −
C:\>
C:\>cd Program Files\MySQL\bin
C:\Program Files\MySQL\bin>
Note − The path to mysqld.exe may vary depending on the install location of MySQL on your system.
You can also check documentation on how to start and stop your database server.
Step 2
Start the database server by executing the following command, if it is already not running.
C:\Program Files\MySQL\bin>mysqld
C:\Program Files\MySQL\bin>
Step 3
Create the TUTORIALSPOINT database by executing the following command −
C:\Program Files\MySQL\bin> mysqladmin create TUTORIALSPOINT -u guest -p
Enter password: ********
C:\Program Files\MySQL\bin>
Create Table
To create the Employees table in TUTORIALSPOINT database, use the following steps −
Step 1
Open a Command Prompt and change to the installation directory as follows −
C:\>
C:\>cd Program Files\MySQL\bin
C:\Program Files\MySQL\bin>
Step 2
Login to the database as follows −
C:\Program Files\MySQL\bin>mysql -u guest -p
Enter password: ********
mysql>
Step 3
Create the table Employees as follows −
mysql> use TUTORIALSPOINT;
mysql> create table Employees
-> (
-> id int not null,
-> age int not null,
-> first varchar (255),
-> last varchar (255)
-> );
Query OK, 0 rows affected (0.08 sec)
mysql>
mysql>
Sample Code
This sample example can serve as a template when you need to create your own JDBC application in
the future.
This sample code has been written based on the environment and database setup done in the previous
chapter.
Copy and paste the following example in FirstExample.java, compile and run as follows −
import java.sql.*;
Approach I - Class.forName()
The most common approach to register a driver is to use Java's Class.forName() method, to dynamically
load the driver's class file into memory, which automatically registers it. This method is preferable
because it allows you to make the driver registration configurable and portable.
The following example uses Class.forName( ) to register the Oracle driver −
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch(ClassNotFoundException ex) {
System.out.println("Error: unable to load driver class!");
System.exit(1);
}
You can use getInstance() method to work around noncompliant JVMs, but then you'll have to code for
two extra Exceptions as follows −
try {
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
}
catch(ClassNotFoundException ex) {
System.out.println("Error: unable to load driver class!");
System.exit(1);
catch(IllegalAccessException ex) {
System.out.println("Error: access problem while loading!");
System.exit(2);
catch(InstantiationException ex) {
System.out.println("Error: unable to instantiate driver!");
System.exit(3);
}
Approach II - DriverManager.registerDriver()
The second approach you can use to register a driver, is to use the
static DriverManager.registerDriver() method.
You should use the registerDriver() method if you are using a non-JDK compliant JVM, such as the one
provided by Microsoft.
The following example uses registerDriver() to register the Oracle driver −
try {
Driver myDriver = new oracle.jdbc.driver.OracleDriver();
DriverManager.registerDriver( myDriver );
}
catch(ClassNotFoundException ex) {
System.out.println("Error: unable to load driver class!");
System.exit(1);
}
All the highlighted part in URL format is static and you need to change only the remaining part as per
your database setup.
A Properties object holds a set of keyword-value pairs. It is used to pass driver properties to the driver
during a call to the getConnection() method.
To make the same connection made by the previous examples, use the following code −
import java.util.*;
Type Description
ResultSet.TYPE_FORWARD_ONLY The cursor can only move forward in the result set.
ResultSet.TYPE_SCROLL_INSENSITIVE The cursor can scroll forward and backward, and the
result set is not sensitive to changes made by others
to the database that occur after the result set was
created.
ResultSet.TYPE_SCROLL_SENSITIVE. The cursor can scroll forward and backward, and the
result set is sensitive to changes made by others to
the database that occur after the result set was
created.
Concurrency of ResultSet
The possible RSConcurrency are given below. If you do not specify any Concurrency type, you will
automatically get one that is CONCUR_READ_ONLY.
Concurrency Description
All our examples written so far can be written as follows, which initializes a Statement object to create a
forward-only, read only ResultSet object −
try {
Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
}
catch(Exception ex) {
....
}
finally {
....
}
Moves the cursor the given number of rows forward or backward, from where it is
currently pointing.
Moves the cursor to the previous row. This method returns false if the previous row is off
the result set.
Moves the cursor to the next row. This method returns false if there are no more rows in
the result set.
Moves the cursor to a special row in the result set that can be used to insert a new row into
the database. The current cursor location is remembered.
Moves the cursor back to the current row if the cursor is currently at the insert row;
otherwise, this method does nothing
Returns the int in the current row in the column named columnName.
Returns the int in the current row in the specified column index. The column index starts at
1, meaning the first column of a row is 1, the second column of a row is 2, and so on.
Similarly, there are get methods in the ResultSet interface for each of the eight Java primitive types, as
well as common types such as java.lang.String, java.lang.Object, and java.net.URL.
There are also methods for getting SQL data types java.sql.Date, java.sql.Time, java.sql.TimeStamp,
java.sql.Clob, and java.sql.Blob. Check the documentation for more information about using these SQL
data types.
For a better understanding, let us study Viewing - Example Code.
Similar to the previous method, except that the column is specified by its name instead of
its index.
There are update methods for the eight primitive data types, as well as String, Object, URL, and the SQL
data types in the java.sql package.
Updating a row in the result set changes the columns of the current row in the ResultSet object, but not
in the underlying database. To update your changes to the row in the database, you need to invoke one of
the following methods.
Updates the current row by updating the corresponding row in the database.
Refreshes the data in the result set to reflect any recent changes in the database.
4 public void cancelRowUpdates()
Inserts a row into the database. This method can only be invoked when the cursor is
pointing to the insert row.
Example
The following code snippet provides an example of a batch update using Statement object −
// Create statement object
Statement stmt = conn.createStatement();
// Set auto-commit to false
conn.setAutoCommit(false);
JDBC –Transactions
If your JDBC Connection is in auto-commit mode, which it is by default, then every SQL statement is
committed to the database upon its completion.
That may be fine for simple applications, but there are three reasons why you may want to turn off the
auto-commit and manage your own transactions −
To increase performance.
To maintain the integrity of business processes.
To use distributed transactions.
Transactions enable you to control if, and when, changes are applied to the database. It treats a single
SQL statement or a group of SQL statements as one logical unit, and if any statement fails, the whole
transaction fails.
To enable manual- transaction support instead of the auto-commit mode that the JDBC driver uses by
default, use the Connection object's setAutoCommit() method. If you pass a boolean false to
setAutoCommit( ), you turn off auto-commit. You can pass a boolean true to turn it back on again.
For example, if you have a Connection object named conn, code the following to turn off auto-commit −
conn.setAutoCommit(false);
Otherwise, to roll back updates to the database made using the Connection named conn, use the
following code −
conn.rollback( );
The following example illustrates the use of a commit and rollback object −
try{
//Assume a valid connection object conn
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
In this case, none of the above INSERT statement would success and everything would be rolled back.
For a better understanding, let us study the Commit - Example Code.
Using Savepoints
The new JDBC 3.0 Savepoint interface gives you the additional transactional control. Most modern
DBMS, support savepoints within their environments such as Oracle's PL/SQL.
When you set a savepoint you define a logical rollback point within a transaction. If an error occurs past
a savepoint, you can use the rollback method to undo either all the changes or only the changes made
after the savepoint.
The Connection object has two new methods that help you manage savepoints −
setSavepoint(String savepointName) − Defines a new savepoint. It also returns a Savepoint
object.
releaseSavepoint(Savepoint savepointName) − Deletes a savepoint. Notice that it requires a
Savepoint object as a parameter. This object is usually a savepoint generated by the
setSavepoint() method.
There is one rollback (String savepointName) method, which rolls back work to the specified
savepoint.
The following example illustrates the use of a Savepoint object −
try{
//Assume a valid connection object conn
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
//set a Savepoint
Savepoint savepoint1 = conn.setSavepoint("Savepoint1");
String SQL = "INSERT INTO Employees " +
"VALUES (106, 20, 'Rita', 'Tez')";
stmt.executeUpdate(SQL);
//Submit a malformed SQL statement that breaks
String SQL = "INSERTED IN Employees " +
"VALUES (107, 22, 'Sita', 'Tez')";
stmt.executeUpdate(SQL);
// If there is no error, commit the changes.
conn.commit();
}catch(SQLException se){
// If there is any error.
conn.rollback(savepoint1);
}
In this case, none of the above INSERT statement would success and everything would be rolled back.