0% found this document useful (0 votes)
55 views

Unit4 Java

Threads are lightweight processes that share memory but execute independently. A thread goes through various states during its lifecycle including new, active, waiting, timed waiting, and terminated. There are two ways to create threads in Java: by extending the Thread class or implementing the Runnable interface. Multithreading allows concurrent execution of parts of a program to maximize CPU utilization. Threads can have different priorities between 1-10 that determine scheduling order, though scheduling is ultimately up to the JVM. Synchronization controls access to shared resources using locks and wait/notify methods for inter-thread communication. Legacy classes like Vector predate the collections framework but provide synchronized dynamic arrays.

Uploaded by

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

Unit4 Java

Threads are lightweight processes that share memory but execute independently. A thread goes through various states during its lifecycle including new, active, waiting, timed waiting, and terminated. There are two ways to create threads in Java: by extending the Thread class or implementing the Runnable interface. Multithreading allows concurrent execution of parts of a program to maximize CPU utilization. Threads can have different priorities between 1-10 that determine scheduling order, though scheduling is ultimately up to the JVM. Synchronization controls access to shared resources using locks and wait/notify methods for inter-thread communication. Legacy classes like Vector predate the collections framework but provide synchronized dynamic arrays.

Uploaded by

poomanim
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

UNIT - IV

Threads:
Threads can be defined as a subprocess with lightweight with the smallest unit of processes and
also has separate paths of execution. These threads use shared memory but they act
independently hence if there is an exception in threads that do not affect the working of other
threads despite them sharing the same memory.

Life Cycle of Thread


There are different states Thread transfers into during its lifetime. They are:
1. New State
2. Active State
3. Waiting/Blocked State
4. Timed Waiting State
5. Terminated State

There are two ways to create a thread:


1. By extending Thread class
2. By implementing Runnable interface.

1) Java Thread Example by extending Thread class

class Multi extends Thread{


public void run(){
System.out.println("thread is running...");
}
public static void main(String args[]){
Multi t1=new Multi();
t1.start();
}
}
Output:
thread is running...

2) Java Thread Example by implementing Runnable interface


class Multi3 implements Runnable{
public void run(){
System.out.println("thread is running...");
}

public static void main(String args[]){


Multi3 m1=new Multi3();
Thread t1 =new Thread(m1); )
t1.start();
}
}

Output:
thread is running...

Multithread:
Multithreading is a Java feature that allows concurrent execution of two or more parts of a
program for maximum utilization of CPU. Each part of such program is called a thread. So, threads
are light-weight processes within a process.

class MultiThread extends Thread{


public void run(){
System.out.println("Running Thread Name: "+ this.currentThread().getName());
}
}
public class MultiThrd {
public static void main(String[] args) {
MultiThread multiThread1 = new MultiThread(“First Thread”);
MultiThread multiThread2 = new MultiThread(“Second Thread”);
MultiThread multiThread3 = new MultiThread(“Third Thread”);
multiThread1.start();
multiThread2.start();
multiThread3.start();
}
}

OUTPUT:
Running Thread Name: First Thread
Running Thread Name: Second Thread
Running Thread Name: Third Thread

Priority of a Thread (Thread Priority):


Each thread has a priority. Priorities are represented by a number between 1 and 10. In most cases,
the thread scheduler schedules the threads according to their priority (known as preemptive
scheduling). But it is not guaranteed because it depends on JVM specification that which
scheduling it chooses. Note that not only JVM a Java programmer can also assign the priorities of
a thread explicitly in a Java program.

Methods:
public final int getPriority():
The java.lang.Thread.getPriority() method returns the priority of the given thread.

public final void setPriority(int newPriority):


The java.lang.Thread.setPriority() method updates or assign the priority of the thread to
newPriority. The method throws IllegalArgumentException if the value newPriority goes out of
the range, which is 1 (minimum) to 10 (maximum).

3 constants defined in Thread class:


1. public static int MIN_PRIORITY
2. public static int NORM_PRIORITY
3. public static int MAX_PRIORITY

Default priority of a thread is 5 (NORM_PRIORITY). The value of MIN_PRIORITY is 1 and the


value of MAX_PRIORITY is 10.

public class A implements Runnable


{
public void run()
{
System.out.println(Thread.currentThread());
}
public static void main(String[] args)
{
A a = new A();
Thread t1 = new Thread(a, "First Thread");
Thread t2 = new Thread(a, "Second Thread");
Thread t3 = new Thread(a, "Third Thread");

t1.setPriority(4);
t2.setPriority(2);
t3.setPriority(8);

t1.start();
t2.start();
t3.start();
}
}
Output:
Thread[Third Thread,8,main]
Thread[First Thread,4,main]
Thread[Second Thread,2,main]

Applying Synchronization:
Synchronization in Java is the capability to control the access of multiple threads to any shared
resource.
There are two types of thread synchronization mutual exclusive and inter-thread communication.
1. Mutual Exclusive
1. Synchronized method.
2. Synchronized block.
3. Static synchronization.
2. Cooperation (Inter-thread communication in java)

Concept of Lock in Java


Synchronization is built around an internal entity known as the lock or monitor. Every object has a
lock associated with it. By convention, a thread that needs consistent access to an object's fields
has to acquire the object's lock before accessing them, and then release the lock when it's done
with them.

Java Synchronized Method


If you declare any method as synchronized, it is known as synchronized method.
Synchronized method is used to lock an object for any shared resource.
When a thread invokes a synchronized method, it automatically acquires the lock for that object
and releases it when the thread completes its task.

class Table{
synchronized void printTable(int n){
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}
catch(Exception e){
System.out.println(e);}
}
}
}

class MyThread1 extends Thread{


Table t;
MyThread1(Table t){
this.t=t;
}
public void run(){
t.printTable(5);
}
}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
}
}
public class TestSynchronization2{
public static void main(String args[]){
Table obj = new Table();
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
} }

Output:
5
10
15
20
25
100
200
300
400
500

Inter-thread communication
Inter-thread communication or Co-operation is all about allowing synchronized threads to
communicate with each other.
Cooperation (Inter-thread communication) is a mechanism in which a thread is paused running in
its critical section and another thread is allowed to enter (or lock) in the same critical section to be
executed. It is implemented by following methods of Object class:
o wait()
o notify()
o notifyAll()

Working process of ITC:


1. Threads enter to acquire lock.
2. Lock is acquired by on thread.
3. Now thread goes to waiting state if you call wait() method on the object. Otherwise it
releases the lock and exits.
4. If you call notify() or notifyAll() method, thread moves to the notified state (runnable
state).
5. Now thread is available to acquire lock.
6. After completion of the task, thread releases the lock and exits the monitor state of the
object.

class Customer{
int amount=10000;

synchronized void withdraw(int amount){


System.out.println("going to withdraw...");

if(this.amount<amount){
System.out.println("Less balance; waiting for deposit...");
try{
wait();
}
catch(Exception e)
{}
}
this.amount-=amount;
System.out.println("withdraw completed...");
}

synchronized void deposit(int amount){


System.out.println("going to deposit...");
this.amount+=amount;
System.out.println("deposit completed... ");
notify();
}
}

class Test{
public static void main(String args[]){
final Customer c=new Customer();
new Thread()
{
public void run(){
c.withdraw(15000);
}
}.start();

new Thread(){
public void run(){
c.deposit(10000);
}
}.start();
}}

Output:
going to withdraw...
Less balance; waiting for deposit...
going to deposit...
deposit completed...
withdraw completed

Legacy Classes:
In the early version of Java, we have several classes and interfaces which allow us to store objects.
After adding the Collection framework in JSE 1.2, for supporting the collections framework, these
classes were re-engineered. So, classes and interfaces that formed the collections framework in the
older version of Java are known as Legacy classes. For supporting generic in JDK5, these classes
were re-engineered.
All the legacy classes are synchronized. The java.util package defines the following legacy classes:
1. HashTable
2. Stack
3. Dictionary
4. Properties
5. Vector

Vector Class:
It is a special type of ArrayList that defines a dynamic array. The java.util.Vector class implements
a growable array of objects. Like an array, it contains components that can be accessed using an
integer index. However, the size of a Vector can grow or shrink as needed to accommodate adding
and removing items after the Vector has been created. It extends AbstractList and implements List
interfaces.

import java.util.*;
public class VectorDemo {

public static void main(String args[]) {


Vector v = new Vector(3, 2);
System.out.println("Initial size: " + v.size());
System.out.println("Initial capacity: " + v.capacity());

v.addElement(new Integer(1));
v.addElement(new Integer(2));
v.addElement(new Integer(3));
v.addElement(new Integer(4));
System.out.println("Capacity after four additions: " + v.capacity());

v.addElement(new Double(5.45));
System.out.println("Current capacity: " + v.capacity());

v.addElement(new Double(6.08));
v.addElement(new Integer(7));
System.out.println("Current capacity: " + v.capacity());

v.addElement(new Float(9.4));
v.addElement(new Integer(10));
System.out.println("Current capacity: " + v.capacity());

v.addElement(new Integer(11));
v.addElement(new Integer(12));
System.out.println("First element: " + (Integer)v.firstElement());
System.out.println("Last element: " + (Integer)v.lastElement());

if(v.contains(new Integer(3)))
System.out.println("Vector contains 3.");

Enumeration vEnum = v.elements();


System.out.println("\nElements in vector:");
while(vEnum.hasMoreElements())
System.out.print(vEnum.nextElement() + " ");
System.out.println();
}
}

OUTPUT:
Initial size: 0
Initial capacity: 3
Capacity after four additions: 5
Current capacity: 5
Current capacity: 7
Current capacity: 9
First element: 1
Last element: 12
Vector contains 3.

Elements in vector:
1 2 3 4 5.45 6.08 7 9.4 10 11 12

Stack Class:
A stack is an ADT – Abstract Data Type or a linear data structure. It is a LIFO data structure
because it allows all data operations at one end only i.e. elements can be added and removed from
the stack only at the top. LIFO stands for Last-in-first-out. The element which is inserted last, is
accessed first.

Stack operations:
 push(): Pushing an element on the stack.
 pop(): Removing an element from the stack.
 peek(): Get the top data element of the stack, without removing it.
 isFull(): Check if stack is full.
 isEmpty(): Check if stack is empty.

Stack states
 Overflow state: A stack is in overflow state if it does not contain enough space to accept an
entity to be pushed.
 Underflow state: A stack is in underflow state if we want to operate stack with pop
operation and the stack is empty.

import java.util.*;
import java.io.*;

public class StackDemo {


public static void main(String args[])
{
Stack<String> stack = new Stack<String>();
stack.push("Welcome");
stack.push("To");
stack.push("Java");
stack.push("Programming");
stack.push("Lab");
System.out.println("Initial Stack: " + stack);
System.out.println("The element at the top of the + " stack is: " + stack.peek());
System.out.println("Popped element: "+ stack.pop());
System.out.println("Popped element: "+ stack.pop());
System.out.println("Final Stack after Pop: " + stack);
}
}

Output:
Initial Stack: [Welcome, To, Java, Programming, Lab]
The element at the top of the stack is: Lab
Popped element: Lab
Popped element: Programming
Final Stack after pop : [Welcome, To, Java]

Legacy Interface:
There is only one legacy interface Enumeration.

Enumeration Interface:
java.util.Enumeration interface is one of the predefined interfaces, whose object is used for
retrieving the data from collections framework variable( like Stack, Vector, HashTable etc.) in a
forward direction only and not in the backward direction. This interface has been superceded by an
iterator.
The Enumeration Interface defines the functions by which we can enumerate the elements in a
collection of elements. For new code, Enumeration is considered obsolete. However, several
methods of the legacy classes such as vectors and properties, several API classes, application
codes use this Enumeration interface.

Important Features
 Enumeration is Synchronized.
 It does not support adding, removing, or replacing elements.
 Elements of legacy Collections can be accessed in a forward direction using Enumeration.
 Legacy classes have methods to work with enumeration and returns Enumeration objects.

import java.util.Vector;
import java.util.Enumeration;

public class EnumerationClass {

public static void main(String args[])


{
Enumeration months;
Vector<String> monthNames = new Vector<>();
monthNames.add("January");
monthNames.add("February");
monthNames.add("March");
monthNames.add("April");
monthNames.add("May");
monthNames.add("June");
monthNames.add("July");
monthNames.add("August");
monthNames.add("September");
monthNames.add("October");
monthNames.add("November");
monthNames.add("December");
months = monthNames.elements();
while (months.hasMoreElements()) {
System.out.println(months.nextElement());
}
}
}

OUTPUT:
January
February
March
April
May
June
July
August
September
October
November
December

Introduction to Utility classes:


The java.util package in Java is a built-in package that contains various utility classes and
interfaces. It provides basic functionality for commonly occurring use cases.
It contains the collections framework, legacy collection classes, event model, date and time
facilities, internationalization, and miscellaneous utility classes (a string tokenizer, a random-
number generator, and a bit array).
Collections Framework in Java is a special part of the java.util package that can be used to
represent and manipulate collections. It provides easy storage and organization of a group of
objects (or collection). It includes pre-written classes, interfaces, and algorithms under a unified
architecture.
StringTokenizer:
The java.util.StringTokenizer class allows you to break a String into tokens. It is simple way to
break a String. It is a legacy class of Java. A StringTokenizer object internally maintains a current
position within the string to be tokenized. Some operations advance this current position past the
characters processed.
A token is returned by taking a substring of the string that was used to create the StringTokenizer
object. It provides the first step in the parsing process often called lexer or scanner. The String
Tokenizer class allows an application to break strings into tokens.
It implements the Enumeration interface. This class is used for parsing data. To use String
Tokenizer class we have to specify an input string and a string that contains delimiters. Delimiters
are the characters that separate tokens. Each character in the delimiter string is considered a valid
delimiter. Default delimiters are whitespaces, new line, space, and tab.
import java.util.StringTokenizer;
public class Simple{
public static void main(String args[]){
StringTokenizer st = new StringTokenizer("I am Learning Java Programming "," ");
System.out.println("Total number of Tokens: "+st.countTokens());
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
}
}

OUTPUT:
Total number of Tokens: 5
I
am
Learning
Java
Programming

Date class:
The java.util.Date class represents date and time in java. It provides constructors and methods to
deal with date and time in java.
The java.util.Date class implements Serializable, Cloneable and Comparable<Date> interface. It is
inherited by java.sql.Date, java.sql.Time and java.sql.Timestamp interfaces.
After Calendar class, most of the constructors and methods of java.util.Date class has been
deprecated. Here, we are not giving list of any deprecated constructor and method.
public class Main
{
public static void main(String[] args)
{
Date d1 = new Date(2000, 11, 21);
Date d2 = new Date(); // Current date
Date d3 = new Date(2010, 1, 3);

boolean a = d3.after(d1);
System.out.println("Date d3 comes after " + "date d2: " + a);

boolean b = d3.before(d2);
System.out.println("Date d3 comes before " + "date d2: " + b);

int c = d1.compareTo(d2);
System.out.println(c);

System.out.println("Miliseconds from Jan 1 " + "1970 to date d1 is " + d1.getTime());

System.out.println("Before setting "+d2);


d2.setTime(204587433443L);
System.out.println("After setting "+d2);
}
}
OUTPUT:
Date d3 comes after date d2: true
Date d3 comes before date d2: false
1
Miliseconds from Jan 1 1970 to date d1 is 60935500800000
Before setting Tue Jul 12 13:13:16 UTC 2016
After setting Fri Jun 25 21:50:33 UTC 1976

Calendar:
Java Calendar class is an abstract class that provides methods for converting date between a
specific instant in time and a set of calendar fields such as MONTH, YEAR, HOUR, etc. It inherits
Object class and implements the Comparable interface.

import java.util.*;
public class Calendar2
{
public static void main(String[] args)
{
Calendar calendar = Calendar.getInstance();
System.out.println("Current Calendar's Year: " + calendar.get(Calendar.YEAR));
System.out.println("Current Calendar's Day: " + calendar.get(Calendar.DATE));
System.out.println("Current MINUTE: " + calendar.get(Calendar.MINUTE));
System.out.println("Current SECOND: " + calendar.get(Calendar.SECOND));
}
}

Output:
Current Calendar's Year: 2018
Current Calendar's Day: 28
Current MINUTE: 10
Current SECOND: 45

Gregorian Calendar:
A concrete subclass of the Calendar class is referred to as GregorianCalendar. The
GregorianCalendar class has an implementation of all of its inherited members. The Calendar class
implements the mostly used Gregorian calendar. In order to use the Gregorian calendar in Java, we
import the Java.util.GregorianCalendar class in our program.

import java.util.TimeZone;
import java.util.Locale;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class GregorianCalendarExample1 {
public static void main(String args[])
{
String months[] = { "January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December" };
String arr[] = { "AM", "PM" };

GregorianCalendar obj = new GregorianCalendar();


System.out.print("Today's date = "
+ obj.get(Calendar.DATE) + " " + months[obj.get(Calendar.MONTH)] + ", "
+ obj.get(Calendar.YEAR) + "\n"
+ "Current time = " + obj.get(Calendar.HOUR) + "-"
+ obj.get(Calendar.MINUTE) + "-" + obj.get(Calendar.SECOND) + " "
+ arr[obj.get(Calendar.AM_PM)] + "\n"
+ "Current Time Zone = " + obj.getTimeZone().getDisplayName()
+ "\n" + "Locale = " + Locale.getDefault().getDisplayName());
}
}

Output
Today's date =20 Apr , 2023
Current time =10-21-51 PM
Current Time Zone =GMT +5:30
Locale =English (United States)

Random Class:
Java Random class is used to generate a stream of pseudorandom numbers. The algorithms
implemented by Random class use a protected utility method than can supply up to 32
pseudorandomly generated bits on each invocation.

import java.util.Random;
public class Test {
public static void main(String[] args) {
Random random = new Random();
System.out.println(random.nextInt(10));
System.out.println(random.nextBoolean());
System.out.println(random.nextDouble());
System.out.println(random.nextFloat());
System.out.println(random.nextGaussian());
byte[] bytes = new byte[10];
random.nextBytes(bytes);
System.out.printf("[");
for(int i = 0; i< bytes.length; i++)
{
System.out.printf("%d ", bytes[i]);
}
System.out.printf("]\n");
System.out.println(random.nextLong());
System.out.println(random.nextInt());
long seed = 95;
random.setSeed(seed);
}}

Output:
4
true
0.19674934340402916
0.7372021
1.4877581394085997
[-44 75 68 89 81 -72 -1 -66 -64 117 ]
158739962004803677
-1344764816

Scanner class
Scanner is a class in java.util package used for obtaining the input of the primitive types like int,
double, etc. and strings. Using the Scanner class in Java is the easiest way to read input in a Java
program, though not very efficient if you want an input method for scenarios where time is a
constraint like in competitive programming.
import java.util.Scanner;
public class ScannerDemo1 {
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
char gender = sc.next().charAt(0);
int age = sc.nextInt();
long mobileNo = sc.nextLong();
double cgpa = sc.nextDouble();
System.out.println("Name: " + name);
System.out.println("Gender: " + gender);
System.out.println("Age: " + age);
System.out.println("Mobile Number: " + mobileNo);
System.out.println("CGPA: " + cgpa);
}
}

OUTPUT:
Name: Edison
Gender: M
Age: 40
Mobile Number: 9876543210
CGPA: 9.9

You might also like