Multithreaded Programming
Multithreaded programming basics Concurrency is the ability to run multiple parts of the program in parallel. In Concurrent programming, there are two units of execution: Processes & Threads Processes Definition: Process is an instance of an entire program in execution. A process has a separate execution environment. It has a complete, private set of basic runtime resources; each process has its own memory space Threads Definition: Thread is an execution path or the control flow of execution of a program. Threads exist within a process; every process has at least one thread. Threads share the process's resources, including memory and open files. Threads are called light-weight process.
A single threaded program class ABC {. public void main(..) {.. begin body end 3
A Multithreaded Program Main Thread start start start Thread A Thread B Thread C 4 Threads may switch or exchange data/results
Threads in Java[main thread] A separate process will be created for each Java program within which one default thread (called the Main thread) starts executing the main function. This default thread or the main thread will be created by JVM. It is the thread using which other threads (child threads) can be created Ideally it must be the last thread to finish execution because it performs various shutdown operations. Each thread in java is associated with an instance of the class java.lang.thread.
main thread public class Example { public static void main(string arg[]) { Thread t = Thread.currentThread(); System.out.println("Hi Everyone.. I am a thread.. " + t); t.setname("newmain"); t.setpriority(9); System.out.println("Hi Everyone.. I am the same thread.. " + t); try { for (int i = 0; i < 5; i++) { Thread.sleep(1000); System.out.println(i); catch (InterruptedException e) { e.printstacktrace();
Creating a Thread Threads in java can be created in two possible ways By implementing Runnable interface By extending Thread class
Creating a thread by implementing Step 1: Runnable interface Simply define your own class and implement it by java.lang.runnable interface. Define run() method, because run() is the entry point for a thread and when it returns from this function, the thread dies. Instance of this class is called Runnable object since it implements Runnable interface.
Creating a thread by implementing Runnable interface Step 1: class MyThread implements Runnable { public void run() { System.out.println("Child thread started.. "); try { for (int i = 0; i < 5; i++) {Thread.sleep(1000); System.out.println("Child.. " + i); System.out.println("Child thread exiting.. "); catch (InterruptedException e) { e.printstacktrace();
Creating a thread by implementing Runnable interface Step 2: Creating a child thread is nothing but creating an instance of Thread class and passing the runnable object as a parameter for its constructor. invoke start() method of the thread object you just created. It causes the child thread to start its execution. The JVM calls run() method of the child thread. It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
Creating a thread by implementing Runnable interface Step 2: public class Example { public static void main(string arg[]) { // Runnable Object MyThread m1 = new MyThread(); //Create a child thread Thread t1 = new Thread(m1); //Start (run) a child thread t1.start(); try { for (int i = 0; i < 5; i++) { Thread.sleep(1000); System.out.println("Main.. " + i); System.out.println("Main thread exiting.. "); catch (InterruptedException e) { e.printstacktrace();
Creating a thread by implementing Runnable interface Optimized version of the program class MyThread implements Runnable { Thread t; MyThread() { t =newthread(this); t.start(); public void run() { System.out.println("Child thread started.. "); try { for (int i = 0; i < 5; i++) { Thread.sleep(1000); System.out.println("Child.. " + i); System.out.println("Child thread exiting.. "); catch (InterruptedException e) { e.printstacktrace();
Creating a thread by implementing Runnable interface Optimized version of the program contd public class Test { public static void main(string arg[]) {// Runnable Object MyThread m1 = new MyThread(); try { for (int i = 0; i < 5; i++) { Thread.sleep(1000); System.out.println("Main.. " + i); System.out.println("Main thread exiting.. "); catch (InterruptedException e) { e.printstacktrace();
Creating a thread by extending Thread class Step 1: Simply extend your own class with java.lang.thread. Define run() method class MyThread extends Thread{ public void run() { System.out.println("Child thread started.. "); try { for (int i = 0; i < 5; i++) { Thread.sleep(1000); System.out.println("Child.. " + i); System.out.println("Child thread exiting.. "); catch (InterruptedException e) { e.printstacktrace();
Creating a thread by extending Thread class Step 2: invoke the run() method of the object created. public class Test2 { public static void main(string arg[]) { // Runnable Object MyThread m1 = new MyThread(); // Start a thread m1.start(); try {for (int i = 0; i < 5; i++) { Thread.sleep(1000); System.out.println("Main.. " + i); System.out.println("Main thread exiting.. "); catch (InterruptedException e) { e.printstacktrace();
Runnable interface is preferred over extending the Thread class Inheritance should be done only if you are modifying or enhancing the base class behavior. Since our class doesn't modify or enhance the Thread class behavior, extending the Thread class is not recommended. If you extend the Thread class, you now don't have freedom of extending other classes (since multiple inheritances are not allowed). So we prefer implementing the Runnable interface and extending any other class.
Creating multiple threads You can create as many threads as you want. given example creates four threads and starts them so that the four child threads along with the main thread prints the numbers 0 to 4 concurrently. assigning a name to the child thread by passing the name as a String argument to the Thread class constructor.
Creating multiple threads class MyThread implements Runnable { Thread t; MyThread(String name) { t =newthread(this, name);// 'name' is the child thread's name t.start(); public void run() { System.out.println("New Thread started with the name"+thread.currentthread().getname()); try { for (int i = 0; i < 5; i++) { Thread.sleep(1000); System.out.println(Thread.currentThread().getName()+".. " + i); System.out.println(Thread.currentThread().getName()+" exiting.."); catch (InterruptedException e) { e.printstacktrace();
Creating multiple threads contd.. public class Test { public static void main(string arg[]) { // Runnable Object MyThread m1 = new MyThread("ChildOne"); MyThread m2 = new MyThread("ChildTwo"); MyThread m3 = new MyThread("ChildThree"); MyThread m4 = new MyThread("ChildFour"); try { for (int i = 0; i < 5; i++) { Thread.sleep(1000); System.out.println("Main.. " + i); System.out.println("Main thread exiting.. "); catch (InterruptedException e) { e.printstacktrace();
Thread Methods Extending Thread Class is required to 'override run()' method. The run method contains the actual logic to be executed by thread. Creation of thread object never starts execution, we need to call 'start()' method to run a thread. join(): It makes to wait for this thread to die. You can wait for a thread to finish by calling its join() method. sleep(): It makes current executing thread to sleep for a specified interval of time. Time is in milli seconds. yield(): It makes current executing thread object to pause temporarily and gives control to other thread to execute. notify(): This method is inherited from Object class. This method wakes up a single thread that is waiting on this object's monitor to acquire lock. notifyall(): This method is inherited from Object class. This method wakes up all threads that are waiting on this object's monitor to acquire lock. wait(): This method is inherited from Object class. This method makes current thread to wait until another thread invokes the notify() or the notifyall() for this object
Different states of a Thread
isalive() and join() How will a one thread know whether another thread has ended or not? isalive() and join() are two different methods to check whether a thread has finished its execution. isalive() General form: final Boolean isalive() Returns true if thread is still running or false otherwise. join() General form: final void join() throws InterruptedException Method waits until the thread on which it is called terminates. Name tells you calling thread waits until specified thread joins it.
Thread priorities In Java, each thread is assigned priority, which affects the order in which it is scheduled for running. The threads so far had same default priority (ORM_PRIORITY) and they are served using FCFS policy. Java allows users to change priority: ThreadName.setPriority(intNumber) MIN_PRIORITY = 1 NORM_PRIORITY=5 MAX_PRIORITY=10
Example Thread priorities class MyThread implements Runnable { Thread t; int count=0; MyThread(String name, int pri) { t =newthread(this, name); t.setpriority(pri); t.start(); public void run() { while (true) { count++;
Example Thread priorities contd.. public class Test { public static void main(string arg[]) {// Runnable Object MyThread m1 = new MyThread("LowPriorityThread", Thread.MIN_PRIORITY); MyThread m2 = new MyThread("HighPriorityThread", Thread.MAX_PRIORITY); try { Thread.sleep(10000); catch (InterruptedException e) { e.printstacktrace(); System.out.println("Low priority thread's execution count.."+m1.count); System.out.println("High priority thread's execution count.."+m2.count);
Synchronization Definition Whenever two or more threads accesses the shared resources we need some mechanism to make sure that only one thread is given access to the shared resource at any point of time. The process by which this is achieved is called synchronization. This is to avoid the following problems: Visibility problem: It occurs if thread A reads shared data and thread B later changes this data and the thread A is unaware of this change. Access problem: It occurs if several threads tries to access and share the same shared data at the same time. How synchronization works The block of code or in general any resources, which is shared among more than two threads and which needs to be synchronized, is called a monitor (also known as semaphore). Only one thread can access the monitor at any point of time. When a thread enters the monitor, we say that the thread has acquired the lock, and it prevents any other threads entering into the same monitor until it releases the lock by exiting the monitor.
Synchronization Problem demonstration Given program has a class named Utility which defines a method called printmessage(string). It takes a string argument and prints it within the flower braces { and. When two threads accesses this method at the same time each one passing a different string argument, the order in which these messages are printed are not jumbled (mixed up).
Example without Synchronization class Utility { // this is the shared resource public void printmessage(string msg) { System.out.print("{"); System.out.print(msg); System.out.println(""); class MyThread implements Runnable { Thread t; Utility util; String msg; MyThread(Utility util, String msg) { t =newthread(this); this.util= util; this.msg= msg; t.start(); public void run() { util.printmessage(msg);
Example without Synchronization contd.. public class Example { public static void main(string arg[]) { Utility util = new Utility(); MyThread m1 = new MyThread(util, "Sachin"); MyThread m2 = new MyThread(util, "Kohli");
Synchronization Synchronization in Java can be achieved in two different ways: Using synchronized methods Using synchronized blocks
Using synchronized methods prefix the keyword 'synchronized' to the shared resource which needs to be synchronized. The resource can be a method, variable or any other program elements. Here the shared resource is the printmessage() method. class Utility { // shared resource is synchronized synchronized public void printmessage(string msg) { System.out.print("{"); System.out.print(msg); System.out.println(""); //Include the code MyThread and Example classes here
Using Synchronized blocks class Utility { // include the code here class MyThread implements Runnable { //Include the code here public void run() { synchronized (util) { util.printmessage(msg); //include the code of class Example
Inter thread communication wait(): This method 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(): This method wakes up the first thread that called wait() on the same object. notifyall(): This method wakes up all the threads that called wait() on the same object. The highest priority thread will run first.
Producer Consumer Implementation Example shows an implementation of solution for producer-consumer problem. It consists of four classes. 1. Class Q, the queue you are trying to synchronize. 2. Producer, threaded object that is producing queue entries. 3. Consumer, threaded object that is consuming queue entries. 4. PC, tiny class that creates single Q, Producer, and Consumer.
Example for Producer Consumer Implementation class Q { int n; boolean valueset = false; synchronized int get() { while (!valueset) try { wait(); catch (InterruptedException e) { System.out.println("InterruptedException caught"); System.out.println("Got: " + n); valueset = false; notify(); return n;
Example for Producer Consumer Implementation //code belongs to class Q synchronized void put(int n) { while (valueset) try { wait(); catch (InterruptedException e) { System.out.println("InterruptedException caught"); this.n=n; valueset =true; System.out.println("Put: " + n); notify();
Example for Producer Consumer Implementation class Producer implements Runnable { Q q; Producer(Q q) { this.q = q; new Thread(this, "Producer").start(); public void run() { int i = 0; while (true) { q.put(i++);
Example for Producer Consumer Implementation class Consumer implements Runnable { Q q; Consumer(Q q) { this.q = q; new Thread(this, "Consumer").start(); public void run() { while (true) { q.get();
Example for Producer Consumer Implementation public 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.");
Exercises 1. Create a multithreaded program by using Runnable interface and then create, initialize and start three Thread objects from your class. The threads will execute concurrently and display the following String array elements. String course [ ] = { Java, J2EE, Spring, Struts ; 2. Write a program TestThreadMany.java that takes a positive integer n from the command line and creates exactly n threads that print out their own name