UNIT V CONCURRENT PROGRAMMING

Similar documents
Synchronization synchronization.

Unit 4. Thread class & Runnable Interface. Inter Thread Communication

7. MULTITHREDED PROGRAMMING

04-Java Multithreading

Multitasking. Multitasking allows several activities to occur concurrently on the computer Levels of multitasking: Process based multitasking

JAVA and J2EE UNIT - 4 Multithreaded Programming And Event Handling

27/04/2012. We re going to build Multithreading Application. Objectives. MultiThreading. Multithreading Applications. What are Threads?

MultiThreading 07/01/2013. Session objectives. Introduction. Introduction. Advanced Java Programming Course

Advanced Java Programming Course. MultiThreading. By Võ Văn Hải Faculty of Information Technologies Industrial University of Ho Chi Minh City

Threads Questions Important Questions

Multithreaded Programming Part II. CSE 219 Stony Brook University, Department of Computer Science

Unit - IV Multi-Threading

Only one thread can own a specific monitor

Multithreaded Programming

Software Practice 1 - Multithreading

CONCURRENT API AND PARALLEL PROGRAMMING

CST242 Concurrency Page 1

CMSC 132: Object-Oriented Programming II. Threads in Java

JAVA - MULTITHREADING

JAVA. Lab 12 & 13: Multithreading

Contribution:javaMultithreading Multithreading Prof. Dr. Ralf Lämmel Universität Koblenz-Landau Software Languages Team

Chapter 32 Multithreading and Parallel Programming

Concurrent Programming using Threads

CIS233J Java Programming II. Threads

Unit III Rupali Sherekar 2017

Chair of Software Engineering. Java and C# in depth. Carlo A. Furia, Marco Piccioni, Bertrand Meyer. Java: concurrency

Parallel Programming Practice

CS11 Java. Fall Lecture 7

Parallel Programming Practice

Deadlock. Only one process can use the resource at a time but once it s done it can give it back for use by another process.

CS 455: INTRODUCTION TO DISTRIBUTED SYSTEMS [THREADS] Frequently asked questions from the previous class survey

CS455: Introduction to Distributed Systems [Spring 2019] Dept. Of Computer Science, Colorado State University

Multitasking Multitasking allows several activities to occur concurrently on the computer. A distinction is usually made between: Process-based multit

Lecture 03: Thread API (continue)

Object Oriented Programming. Week 10 Part 1 Threads

Performance Throughput Utilization of system resources

CS 556 Distributed Systems

Java Threads. COMP 585 Noteset #2 1

Threads. Definitions. Process Creation. Process. Thread Example. Thread. From Volume II

Java Threads. Written by John Bell for CS 342, Spring 2018

Contents. 6-1 Copyright (c) N. Afshartous

Handling Multithreading Approach Using Java Nikita Goel, Vijaya Laxmi, Ankur Saxena Amity University Sector-125, Noida UP India

CS 2112 Lecture 20 Synchronization 5 April 2012 Lecturer: Andrew Myers

Basics of. Multithreading in Java

SUMMARY INTRODUCTION CONCURRENT PROGRAMMING THREAD S BASICS. Introduction Thread basics. Thread states. Sequence diagrams

Unit 5 - Exception Handling & Multithreaded

UNIT IV MULTITHREADING AND GENERIC PROGRAMMING

Note: Each loop has 5 iterations in the ThreeLoopTest program.

Object Oriented Programming (II-Year CSE II-Sem-R09)

The Dining Philosophers Problem CMSC 330: Organization of Programming Languages

B2.52-R3: INTRODUCTION TO OBJECT ORIENTATED PROGRAMMING THROUGH JAVA

Concurrent Programming

Multithread Computing

CS61B, Spring 2003 Discussion #17 Amir Kamil UC Berkeley 5/12/03

Concurrent Programming. Copyright 2017 by Robert M. Dondero, Ph.D. Princeton University

CMSC 330: Organization of Programming Languages. The Dining Philosophers Problem

Module - 4 Multi-Threaded Programming

Computation Abstractions. Processes vs. Threads. So, What Is a Thread? CMSC 433 Programming Language Technologies and Paradigms Spring 2007

Interprocess Communication By: Kaushik Vaghani

Overview. Processes vs. Threads. Computation Abstractions. CMSC 433, Fall Michael Hicks 1

Java Threads and intrinsic locks

Info 408 Distributed Applications programming 2 nd semester of 2017/2018 Credits: 5 Lecturer: Dr. Antoun Yaacoub

Advanced Programming Concurrency

Robotics and Autonomous Systems

COURSE 11 PROGRAMMING III OOP. JAVA LANGUAGE

SUMMARY FUTURES CALLABLES CONCURRENT PROGRAMMING THREAD S ADVANCED CONCEPTS

CS 159: Parallel Processing

-Aditya Bhave CSCI-5448 Graduate Presentation

Java Threads. Introduction to Java Threads

THREADS AND MULTITASKING ROBOTS

ROBOTICS AND AUTONOMOUS SYSTEMS

CMSC 330: Organization of Programming Languages

CS 351 Design of Large Programs Threads and Concurrency

Quiz on Tuesday April 13. CS 361 Concurrent programming Drexel University Fall 2004 Lecture 4. Java facts and questions. Things to try in Java

Programmazione Avanzata e Paradigmi Ingegneria e Scienze Informatiche - UNIBO a.a 2013/2014 Lecturer: Alessandro Ricci

Threads Chate Patanothai

Info 408 Distributed Applications Programming Exercise sheet nb. 4

Shared-Memory and Multithread Programming

Chapter 19 Multithreading

CMSC 330: Organization of Programming Languages. Threads Classic Concurrency Problems

Overview. CMSC 330: Organization of Programming Languages. Concurrency. Multiprocessors. Processes vs. Threads. Computation Abstractions

G Programming Languages Spring 2010 Lecture 13. Robert Grimm, New York University

COMP 213. Advanced Object-oriented Programming. Lecture 23. Shared Variables and Synchronization

CS342: Software Design. November 21, 2017

Concurrency - Topics. Introduction Introduction to Subprogram-Level Concurrency Semaphores Monitors Message Passing Java Threads

Informatica 3. Marcello Restelli. Laurea in Ingegneria Informatica Politecnico di Milano 9/15/07 10/29/07

What is a thread anyway?

Introduction to Java Threads

MultiThreading. Object Orientated Programming in Java. Benjamin Kenwright

Part I: Communication and Networking

By: Abhishek Khare (SVIM - INDORE M.P)

Definition: A thread is a single sequential flow of control within a program.

Synchronized Methods of Old Versions of Java

CMSC 433 Programming Language Technologies and Paradigms. Concurrency

Concurrent Programming in C++ Venkat

Advanced Programming Methods. Lecture 6 - Concurrency in Java (1)

Advanced Concepts of Programming

Learning from Bad Examples. CSCI 5828: Foundations of Software Engineering Lecture 25 11/18/2014

Amity School of Engineering

THREADS AND CONCURRENCY

Transcription:

UNIT V CONCURRENT PROGRAMMING Multi-Threading: Java provides built-in support for multithreaded programming. A multithreaded program contains two or more parts that can run concurrently. Each part of such a program is called a thread, and each thread defines a separate path of execution. A multithreading is a specialized form of multitasking. Multitasking threads require less overhead than multitasking processes. A process consists of the memory space allocated by the operating system that can contain one or more threads. A thread cannot exist on its own; it must be a part of a process. A process remains running until all of the non-daemon threads are done executing. Multithreading enables you to write very efficient programs that make maximum use of the CPU, because idle time can be kept to a minimum. Life Cycle of a Thread: A thread goes through various stages in its life cycle. For example, a thread is born, started, runs, and then dies. Following diagram shows complete life cycle of a thread. Above mentioned stages are explained here: New: A new thread begins its life cycle in the new state. It remains in this state until the program starts the thread. It is also referred to as a born thread. Runnable: After a newly born thread is started, the thread becomes runnable. A thread in this state is considered to be executing its task. Waiting: Sometimes a thread transitions to the waiting state while the thread waits for another thread to perform a task.a thread transitions back to the runnable state only when another thread signals the waiting thread to continue executing.

Timed waiting: A runnable thread can enter the timed waiting state for a specified interval of time. A thread in this state transitions back to the runnable state when that time interval expires or when the event it is waiting for occurs. Terminated: A runnable thread enters the terminated state when it completes its task or otherwise terminates. Creating a Thread: Java defines two ways in which this can be accomplished: You can implement the Runnable interface. You can extend the Thread class, itself. Create Thread by Implementing Runnable: The easiest way to create a thread is to create a class that implements the Runnable interface. To implement Runnable, a class need only implement a single method called run( ), which is declared like this: public void run( ) You will define the code that constitutes the new thread inside run() method. It is important to understand that run() can call other methods, use other classes, and declare variables, just like the main thread can. After you create a class that implements Runnable, you will instantiate an object of type Thread from within that class. Thread defines several constructors. The one that we will use is shown here: Thread(Runnable threadob, String threadname); Here threadob is an instance of a class that implements the Runnable interface and the name of the new thread is specified by threadname. After the new thread is created, it will not start running until you call its start( ) method, which is declared within Thread. The start( ) method is shown here: void start( ); Example: Here is an example that creates a new thread and starts it running:

Create Thread by Extending Thread: The second way to create a thread is to create a new class that extends Thread, and then to create an instance of that class. The extending class must

override the run( ) method, which is the entry point for the new thread. It must also call start( ) to begin execution of the new thread. Example: Here is the preceding program rewritten to extend Thread:

Thread Methods: Following is the list of important medthods available in the Thread class. The previous methods are invoked on a particular Thread object. The following methods in the Thread class are static. Invoking one of the static methods performs the operation on the currently running thread

Example: The following ThreadClassDemo program demonstrates some of these methods of the Thread class:

This would produce following result. You can try this example again and again and you would get different result every time. Interrupting thrreads: Interrupting a thread means stopping what it is doing before it has completed its task, effectively aborting its current operation. Whether the thread dies, waits for new tasks, or goes on to the next step depends on the application. Although it may seem simple at first, you must take some precautions in order to achieve the desired result. There are some caveats you must be aware of as well. First of all, forget the Thread.stop method. Although it indeed stops a running thread, the method is unsafe and was deprecated, which means it may not be available in future versions of the Java. Another method that can be confusing for the unadvised is Thread.interrupt. Despite what its name may imply, the method does not interrupt a running thread (more on this later), as Listing A demonstrates. It creates a thread and tries to stop it usingthread.interrupt. The calls to Thread.sleep() give plenty of time for the thread initialization and termination. The thread itself does not do anything useful. Listing A:

If you run the code in Listing A, you should see something like this on your console: Even after Thread.interrupt() is called, the thread continues to run for a while. Really interrupting a thread The best, recommended way to interrupt a thread is to use a shared variable to signal that it must stop what it is doing. The thread must check the variable periodically, especially during lengthy operations, and terminate its task in an orderly manner.listing B demonstrates this technique. Listing B:

} } Running the code in Listing B will generate output like this (notice how the thread exits in an orderly fashion): Although this method requires some coding, it is not difficult to implement and give the thread the opportunity to do any cleanup needed, which is an absolute requirement for any multithreaded application. Just be sure to declare the shared variable as volatile or enclose any access to it into synchronized blocks/methods. So far, so good! But what happens if the thread is blocked waiting for some event? Of course, if the thread is blocked, it can't check the shared variable and can't stop. There are plenty of situations when that may occur, such as calling Object.wait(),ServerSocket.accept(), and DatagramSocket.receive(), to name a few. They all can block the thread forever. Even if a timeout is employed, it may not be feasible or desirable to wait until the timeout expires, so a mechanism to prematurely exit the blocked state must be used. Unfortunately there is no such mechanism that works for all cases, but the particular technique to use depends on each situation. In the following sections, I'll give solutions for the most common cases. Interrupting a thread with Thread.interrupt()

As demonstrated in Listing A, the method Thread.interrupt() does not interrupt a running thread. What the method actually does is to throw an interrupt if the thread is blocked, so that it exits the blocked state. More precisely, if the thread is blocked at one of the methods Object.wait, Thread.join, or Thread.sleep, it receives aninterruptedexception, thus terminating the blocking method prematurely. So, if a thread blocks in one of the aforementioned methods, the correct way to stop it is to set the shared variable and then call the interrupt() method on it (notice that it is important to set the variable first). If the thread is not blocked, calling interrupt() will not hurt; otherwise, the thread will get an exception (the thread must be prepared to handle this condition) and escape the blocked state. In either case, eventually the thread will test the shared variable and stop. Listing C is a simple example that demonstrates this technique. Listing C: As soon as Thread.interrupt() is called in Listing C, the thread gets an exception so that it escapes the blocked state and determines that it should stop. Running this code produces output like this:

Interrupting an I/O operation But what happens if the thread is blocked on an I/O operation? I/O can block a thread for a considerable amount of time, particularly if network communication is involved. For example, a server may be waiting for a request, or a network application may be waiting for an answer from a remote host. If you're using channels, available with the new I/O API introduced in Java 1.4, the blocked thread will get a ClosedByInterruptException exception. If that is the case, the logic is the same as that used in the third example only the exception is different. But you might be using the traditional I/O available since Java 1.0, since the new I/O is so recent and requires more work. In this case, Thread.interrupt() doesn't help, since the thread will not exit the blocked state. Listing D demonstrates that behavior. Although the interrupt() method is called, the thread does not exit the blocked state. Listing D:

Fortunately, the Java Platform provides a solution for that case by calling the close()method of the socket the thread is blocked in. In this case, if the thread is blocked in an I/O operation, the thread will get a SocketException exception, much like theinterrupt() method causes an InterruptedException to be thrown. The only caveat is that a reference to the socket must be available so that its close()method can be called. That means the socket object must also be shared. Listing Edemonstrates this case. The logic is the same as in the examples presented so far. And here's the sample output you can expect from running Listing E: Listing E:

Multithreading is a powerful tool, but it presents its own set of challenges. One of these is how to interrupt a running thread. If properly implemented, these techniques

make interrupting a thread no more difficult than using the built-in operations already provided by the Java Platform. Thread Priorities: Every Java thread has a priority that helps the operating system determine the order in which threads are scheduled. Java priorities are in the range between MIN_PRIORITY (a constant of 1) and MAX_PRIORITY (a constant of 10). By default, every thread is given priority NORM_PRIORITY (a constant of 5). Threads with higher priority are more important to a program and should be allocated processor time before lower-priority threads. However, thread priorities cannot guarantee the order in which threads execute and very much platform dependentant. Setting a threads priority can be very useful if one thread has more critical tasks to perform than another. The Thread class has a method called setpriority(int level) with which you can alter the priority a Thread instance has. The priority level range from 1 (least important) to 10 (most important) and if no level is explicitly set, a Thread instance has the priority level of 5. In the first example below no priorites are set, so both threads have the priority level 5. The TestThread class implements the Runnable interface and in its run() method loops from 1 to 10 and output the number along with its Thread id, which is passed to the constructor.

} } } Since both threads have the same priority, the output will be a mix between them and could look like this: The output could look different from on execution to another since we have no control of how the CPU will prioritize them. If we set the priority on the threads we still

haven't got exact control of the execution, but at least we can tell the CPU which one we think is most important. The next example is identical to the one above except for the lines where the priority of the threads is set:

The output from the code looked like this when executed: It is however not certain that the first thread will be prioritized to finish before the second thread starts every time. It is up to the CPU to decide. Thread 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 synchronization is achieved is called thread synchronization. The synchronized keyword in Java creates a block of code referred to as a critical section. Every Java object with a critical section of code gets a lock associated with the object. To enter a critical section, a thread needs to obtain the corresponding object's lock. This is the general form of the synchronized statement: Here, object is a reference to the object being synchronized. A synchronized block ensures that a call to a method that is a member of object occurs only after the current thread has successfully entered object's monitor. Here is an example, using a synchronized block within the run( ) method:

Interthread Communication: Consider the classic queuing problem, where one thread is producing some data and another is consuming it. To make the problem more interesting, suppose that the producer has to wait until the consumer is finished before it generates more data. In a polling system, the consumer would waste many CPU cycles while it waited for the producer to produce. Once the producer was finished, it would start polling, wasting more CPU cycles waiting for the consumer to finish, and so on. Clearly, this situation is undesirable. To avoid polling, Java includes an elegant interprocess communication mechanism via the following methods: 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.c The highest priority thread will run first. 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. These methods are declared within Object. Various forms of wait( ) exist that allow you to specify a period of time to wait. Example: The following sample program consists of four classes: Q, the queue that you're trying to synchronize; Producer, the threaded object that is producing queue entries; Consumer, the threaded object that is consuming queue entries; and PC, the tiny class that creates the single Q, Producer, and Consumer. The proper way to write this program in Java is to use wait( ) and notify( ) to signal in both directions, as shown here:

Inside get( ), wait( ) is called. This causes its execution to suspend until the Producer notifies you that some data is ready. When this happens, execution inside get( ) resumes. After the data has been obtained, get( ) calls notify( ). This tells Producer that it is okay to put more data in the queue. Inside put( ), wait( ) suspends execution until the Consumer has removed the item from the queue. When execution resumes, the next item of data is put in the queue, and notify( ) is called. This tells the Consumer that it should now remove it. Here is some output from this program, which shows the clean synchronous behavior: Put: 1 Got: 1 Put: 2 Got: 2 Put: 3 Got: 3 Put: 4 Got: 4 Put: 5 Got: 5 Thread Deadlock: A special type of error that you need to avoid that relates specifically to multitasking is deadlock, which occurs when two threads have a circular dependency on a pair of synchronized objects. For example, suppose one thread enters the monitor on object X and another thread enters the monitor on object Y. If the thread in X tries to call any synchronized method on Y, it will block as expected. However, if the thread in Y, in turn, tries to call any synchronized method on X, the thread waits forever, because to access X, it would have to release its own lock on Y so that the first thread could complete.

Because the program has deadlocked, you need to press CTRL-C to end the program. You can see a full thread and monitor cache dump by pressing CTRL-BREAK on a PC. You will see that RacingThread owns the monitor on b, while it is waiting for the monitor on a. At the same time, MainThread owns a and is waiting to get b. This program will never complete. As this example illustrates, if your multithreaded program locks up occasionally, deadlock is one of the first conditions that you should check for. Thread Control: While the suspend( ), resume( ), and stop( ) methods defined by Thread class seem to be a perfectly reasonable and convenient approach to managing the execution of threads, they must not be used for new Java programs and obsolete in newer versions of Java. The following example illustrates how the wait( ) and notify( ) methods that are inherited from Object can be used to control the execution of a thread. This example is similar to the program in the previous section. However, the deprecated method calls have been removed. Let us consider the operation of this program. The NewThread class contains a boolean instance variable named suspendflag, which is used to control the execution of the thread. It is initialized to false by the constructor. The run( ) method contains a synchronized statement block that checks suspendflag. If that variable is true, the wait( ) method is invoked to suspend the execution of the thread. The mysuspend( ) method sets suspendflag to true. The myresume( ) method sets suspendflag to false and invokes notify( ) to wake up the thread. Finally, the main( ) method has been modified to invoke the mysuspend( ) and myresume( ) methods. Example:

Using isalive() and join(): Typically, the main thread is the last thread to finish in a program. However, there isn t any guarantee that the main thread won t finish before a child thread finishes. In the previous example, we told the main method to sleep until the child threads terminate. However, we estimated the time it takes for the child threads to complete processing. If our estimate was too short, a child thread could terminate after the main thread terminates. Therefore, the sleep technique isn t the best one to use to guarantee that the main thread terminates last. Programmers use two other techniques to ensure that the main thread is the last thread to terminate. These techniques involve calling the isalive() method and the join() method. Both of these methods are defined in the Thread class.

The isalive() method determines whether a thread is still running. If it is, the isalive() method returns a Boolean true value; otherwise, a Boolean false is returned. You can use the isalive() method to examine whether a child thread continues to run. The join() method works differently than the isalive() method. The join() method waits until the child thread terminates and joins the main thread. In addition, you can use the join() method to specify the amount of time you want to wait for a child thread to terminate. The following example illustrates how to use the isalive() method and the join() method in your program. This example is nearly the same as the previous example. The difference lies in the main() method of the Demo class definition. After the threads are declared using the constructor of the MyThread class, the isalive() method is called for each thread. The value returned by the isalive() method is then displayed on the screen. Next, the join() method is called for each thread. The join() method causes the main thread to wait for all child threads to complete processing before the main thread terminates.

Here is what is displayed on the screen when this program runs:

Thread Pools: Most of the executor implementations in java.util.concurrent use thread pools, which consist of worker threads. This kind of thread exists separately from the Runnable and Callable tasks it executes and is often used to execute multiple tasks. Using worker threads minimizes the overhead due to thread creation. Thread objects use a significant amount of memory, and in a large-scale application, allocating and deallocating many thread objects creates a significant memory management overhead. One common type of thread pool is the fixed thread pool. This type of pool always has a specified number of threads running; if a thread is somehow terminated while it is still in use, it is automatically replaced with a new thread. Tasks are submitted to the pool via an internal queue, which holds extra tasks whenever there are more active tasks than threads. An important advantage of the fixed thread pool is that applications using it degrade gracefully. To understand this, consider a web server application where each HTTP request is handled by a separate thread. If the application simply creates a new thread for every new HTTP request, and the system receives more requests than it can handle immediately, the application will suddenly stop responding to all requests when the overhead of all those threads exceed the capacity of the system. With a limit on the number of the threads that can be created, the application will not be servicing HTTP requests as quickly as they come in, but it will be servicing them as quickly as the system can sustain. A simple way to create an executor that uses a fixed thread pool is to invoke the newfixedthreadpool factory method in java.util.concurrent.executors This class also provides the following factory methods: The newcachedthreadpool method creates an executor with an expandable thread pool. This executor is suitable for applications that launch many short-lived tasks. The newsinglethreadexecutor method creates an executor that executes a single task at a time. Several factory methods are ScheduledExecutorService versions of the above executors. If none of the executors provided by the above factory methods meet your needs, constructing instances of java.util.concurrent.threadpoolexecutor or java.util.concurrent.scheduledthreadpoolexecutor will give you additional options. Callables: Callables are a tweak to the existing runnable construct. Callables differ only by having a generic return type - most specialized concurrency APIs already available (such as Foxtrot ) already have the concept of a runnable + return type (such as the foxtrot Task

and Job classes). Some of you may already have noticed that the ExecutorService API is biased to Callable objects - and some may consider that a problem since they have a lot of code that already works with Runnable. Type Parameters: V - the result type of method call public interface Callable<V> A task that returns a result and may throw an exception. Implementors define a single method with no arguments called call. The Callable interface is similar to Runnable, in that both are designed for classes whose instances are potentially executed by another thread. A Runnable, however, does not return a result and cannot throw a checked exception. Executors: There's a close connection between the task being done by a new thread, as defined by its Runnable object, and the thread itself, as defined by a Thread object. This works well for small applications, but in large-scale applications, it makes sense to separate thread management and creation from the rest of the application. Objects that encapsulate these functions are known as executors. The Executors class contains utility methods to convert from other common forms to Callable classes. V call() - Computes a result, or throws an exception if unable to do so. Example: import java.util.concurrent.countdownlatch; import java.util.concurrent.executorservice;

import java.util.concurrent.executors;

Synchronizers: Java 5 introduces general purpose synchronizer classes, including semaphores, mutexes, barriers, latches, and exchangers, which facilitate coordination between threads. These classes are a apart of the java.util.concurrent package. A brief description of each of these follows: Semaphores - A counting semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it. Each release() adds a permit, potentially releasing a blocking acquirer. However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly. Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource. Example:

Barrier A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized

group of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.