0% found this document useful (0 votes)
39 views31 pages

Unit 5 Concurrent Programming

Threads are lightweight processes that allow for parallel processing to improve response times and CPU utilization. Java supports threads through the Thread class and Runnable interface. Synchronization is needed to prevent data corruption when multiple threads access shared objects concurrently. The synchronized keyword and explicit locking can be used to synchronize access to shared objects and collections.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39 views31 pages

Unit 5 Concurrent Programming

Threads are lightweight processes that allow for parallel processing to improve response times and CPU utilization. Java supports threads through the Thread class and Runnable interface. Synchronization is needed to prevent data corruption when multiple threads access shared objects concurrently. The synchronized keyword and explicit locking can be used to synchronize access to shared objects and collections.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 31

UNIT 5

CONCURRENT PROGRAMMING
Threads
• Threads are lightweight processes as the
overhead of switching between threads is less
• The can be easily spawned
• The Java Virtual Machine spawns a thread
when your program is run called the Main
Thread
Why do we need threads?
• To enhance parallel processing
• To increase response to the user
• To utilize the idle time of the CPU
• Prioritize your work depending on priority
Example
• Consider a simple web server
• The web server listens for request and serves it
• If the web server was not multithreaded, the
requests processing would be in a queue, thus
increasing the response time and also might hang
the server if there was a bad request.
• By implementing in a multithreaded
environment, the web server can serve multiple
request simultaneously thus improving response
time
Creating threads
• In java threads can be created by extending
the Thread class or implementing the
Runnable Interface
• It is more preferred to implement the
Runnable Interface so that we can extend
properties from other classes
• Implement the run() method which is the
starting point for thread execution
Running threads
• Example
class mythread implements Runnable{
public void run(){
System.out.println(“Thread Started”);
}
}

class mainclass {
public static void main(String args[]){
Thread t = new Thread(new mythread()); // This is the way to
instantiate a thread implementing
runnable interface
t.start(); // starts the thread by running the run method
}
}
• Calling t.run() does not start a thread, it is just a simple
method call.
• Creating an object does not create a thread, calling
start() method creates the thread.
Thread states
new
wait()
start() sleep()
suspend()
blocked

runnable non-runnable
notify()
stop() slept
resume()
unblocked

dead
Threading Mechanisms...
• Create a class that extends the Thread class
• Create a class that implements the Runnable interface
1st method: Extending Thread class
class MyThread extends Thread
{
public void run()
{
// thread body of execution
}
}
• Creating thread:
MyThread thr1 = new MyThread();
• Start Execution:
thr1.start();
An example
class MyThread extends Thread { // the thread
public void run() {
System.out.println(" this thread is running ... ");
}
} // end class MyThread

class ThreadEx2 { // a program that utilizes the thread


public static void main(String [] args ) {
// note, the created object myThreadObject IS A Thread as well.
MyThread t = new MyThread();
// due to extending the Thread class (above)
// I can call start(), and this will call
// run(). start() is a method in class Thread.
t.start();
} // end main()
} // end class ThreadEx2
2nd method: Threads by implementing
Runnable interface
class MyThread implements Runnable
{
.....
public void run()
{
// thread body of execution
}
}
• Creating Object:
MyThread myObject = new MyThread();
• Creating Thread Object:
Thread thr1 = new Thread( myObject );
• Start Execution:
thr1.start();
An example
class MyThread implements Runnable {
public void run() {
System.out.println(" this thread is running ... ");
}
} // end class MyThread

class ThreadEx21 {
public static void main(String [] args ) {
Thread t = new Thread(new MyThread());
// due to implementing the Runnable interface
// I can call start(), and this will call run().
t.start();
} // end main()
} // end class ThreadEx2
A program with two threads
class MyThread implements Runnable {
public void run() { System.out.println("This is
'MyThread' ); }
}

class YourThread implements Runnable {


public void run() { System.out.println("This is
'YourThread'); }
}

class ThreadEx4 {
public static void main(String [] args ) {
Thread t1 = new Thread(new MyThread());
Thread t2 = new Thread(new YourThread());
t1.start();
t2.start();
}
} // end class ThreadEx4
Monitor model (for Syncronization)

Method 1

Method 2

Key
Block 1

Threads

Monitor (synchronized) solves race-condition problem


Synchronization
• Synchronization is prevent data corruption
• Synchronization allows only one thread to
perform an operation on a object at a time.
• If multiple threads require an access to an
object, synchronization helps in maintaining
consistency.
Example
public class Counter{
private int count = 0;
public int getCount(){
  return count;
}

public setCount(int count){


   this.count = count;
}
}
Example
• In this example, the counter tells how many
an access has been made.
• If a thread is accessing setCount and updating
count and another thread is accessing
getCount at the same time, there will be
inconsistency in the value of count.
Fixing the example
public class Counter{
private static int count = 0;
public synchronized int getCount(){
  return count;
}

public synchoronized setCount(int count){


   this.count = count;
}
}
Example
• By adding the synchronized keyword we make
sure that when one thread is in the setCount
method the other threads are all in waiting state.
• The synchronized keyword places a lock on the
object, and hence locks all the other methods
which have the keyword synchronized. The lock
does not lock the methods without the keyword
synchronized and hence they are open to access
by other threads.
What about static methods?
public class Counter{
private int count = 0;
public static synchronized int getCount(){
  return count;
}

public static synchronized setCount(int count){


   this.count = count;
}
}
Common Synchronization mistake
public class Counter{
private int count = 0;
public static synchronized int getCount(){
  return count;
}

public synchronized setCount(int count){


   this.count = count;
}
}
Common Synchronization mistake
• The synchronized keyword locks the object. The wait
keyword waits for the lock to be acquired, if the
object was already locked by another thread.
Notifyall() notifies other threads that the lock is
about to be released by the current thread.
• Another method notify() is available for use, which
wakes up only the next thread which is in queue for
the object, notifyall() wakes up all the threads and
transfers the lock to another thread having the
highest priority.
Common Synchronization mistake
• In this example the methods are static and
hence are associated with the class object and
not the instance.
• Hence the lock is placed on the class object
that is, Counter.class object and not on the
object itself. Any other non static
synchronized methods are still available for
access by other threads.
Object locking
• The object can be explicitly locked in this way
synchronized(myInstance){
try{
wait();
}catch(InterruptedException ex){

}
System.out.println(“Iam in this “);
notifyAll();
}
Object locking
• The synchronized keyword locks the object. The wait
keyword waits for the lock to be acquired, if the
object was already locked by another thread.
Notifyall() notifies other threads that the lock is
about to be released by the current thread.
• Another method notify() is available for use, which
wakes up only the next thread which is in queue for
the object, notifyall() wakes up all the threads and
transfers the lock to another thread having the
highest priority.
Synchronized Collections
•The classes in the Java Collections Framework
are not thread-safe, i.e., the contents may be
corrupted if they are accessed and updated
concurrently by multiple threads.
•You can protect the data in a collection by
locking the collection or using synchronized
collections.
•The Collections class provides six static methods
for wrapping a collection into a synchronized
version.
•The collections created using these methods are
called synchronization wrappers.
java.util.Collections
+synchronizedCollection(c: Collection): Collection Returns a synchronized collection.
+synchronizedList(list: List): List Returns a synchronized list from the specified list.
+synchronizedMap(m: Map): Map Returns a synchronized map from the specified map.
+synchronizedSet(s: Set): Set Returns a synchronized set from the specified set.
+synchronizedSortedMap(s: SortedMap): SortedMap Returns a synchronized sorted map from the specified
sorted map.
+synchronizedSortedSet(s: SortedSet): SortedSet Returns a synchronized sorted set.
Vector, Stack, and Hashtable
Invoking synchronizedCollection(Collection c)
returns a new Collection object, in which all the
methods that access and update the original
collection c are synchronized. These methods are
implemented using the synchronized keyword. For
example, the add method is implemented like this:

public boolean add(E o) {


synchronized (this) { return c.add(o); }
}
Vector, Stack, and Hashtable
The synchronized collections can be safely accessed
and modified by multiple threads concurrently.

The methods in java.util.Vector, java.util.Stack, and


Hashtable are already synchronized. These are old
classes introduced in JDK 1.0. In JDK 1.5, you should
use java.util.ArrayList to replace Vector,
java.util.LinkedList to replace Stack, and
java.util.Map to replace Hashtable. If
synchronization is needed, use a synchronization
wrapper.
Executors
• An Executor is an object that manages running
tasks
– Submit a Runnable to be run with Executor’s
execute() method
– So, instead of creating a Thread for your Runnable
and calling start() on that, do this:
• Get an Executor object, say called exec
• Create a Runnable, say called myTask
• Submit for running: exec.execute(myTask)
How to Get an Executor
• Use static methods in Executors library.
• Fixed “thread pool”: at most N threads running at
one time
Executor exec =
Executors.newFixedThreadPool(MAX_THREADS);
• Unlimited number of threads
Executor exec =
Executors.newCachedThreadPool();

You might also like