Chapter 5 - Multithreading - 015357
Chapter 5 - Multithreading - 015357
Chapter 5 - Multithreading - 015357
Java Programming
Chapter Five
Multithreading
2
Objectives
In this chapter you will learn:
What threads are and why they are useful.
How threads enable you to manage concurrent activities.
The life cycle of a thread.
Thread priorities and scheduling.
To create and execute Runnables.
Thread synchronization
3
Introduction
One of the powerful features of Java is its built-in
support for multithreading.
Multithreading: the concurrent running of multiple
tasks within a program.
In many programming languages, you have to invoke
system-dependent procedures and functions to
implement multithreading.
This chapter introduces the concepts of threads and how
to develop multithreading programs in Java.
4
Thread Concepts
A program may consist of many tasks that can run
concurrently.
A thread is the flow of execution, from beginning to
end, of a task. It provides the mechanism for running a
task.
With Java, you can launch multiple threads from a
program concurrently.
These threads can be executed simultaneously in
multiprocessor systems.
5
Thread Concepts (cont’d)
6
Thread Concepts (cont’d)
Multithreading can make your program more
responsive and interactive, as well as enhance
performance.
For example,
A good word processor lets you print or save a file while you
are typing.
When downloading a large file, we can put multiple threads to
work—one to download the clip, and another to play it.
Threads:
Threads are so called lightweight processes which have their
own call stack but can access shared data.
Every thread has its own memory cache. If a thread reads
shared data it stores this data in its own memory cache.
8
Thread States
Java thread can be in one of these states:
New – thread allocated & waiting for start()
Runnable – thread can execute
Blocked – thread waiting for event (I/O, etc.)
Terminated – thread finished
9
Thread States (cont’d)
Thread States
10
Creating and Executing Threads
The preferred means of creating multithreaded Java
applications is by implementing the Runnable interface.
A Runnable object represents a “task” that can execute
concurrently with other tasks.
The Runnable interface declares a single method, run.
You need to implement run method to tell the system
how your thread is going to run.
11
Creating and Executing Threads(cont’d)
12
Creating and Executing Threads(cont’d)
Example 1
13
Creating and Executing Threads(cont’d)
Example 2
14
Creating and Executing Threads(cont’d)
public static void main(String[] args) {
15
Creating and Executing Threads(cont’d)
Example 3
public class TaskThreadDemo {
public static void main(String[] args) {
// Create tasks
PrintChar printA = new PrintChar('a', 100);
PrintChar printB = new PrintChar('b', 100);
PrintNum print100 = new PrintNum(100);
// Create threads
Thread thread1 = new Thread(printA);
Thread thread2 = new Thread(printB);
Thread thread3 = new Thread(print100);
// Start threads
thread1.start();
thread2.start();
thread3.start();
}
}
16
Creating and Executing Threads(cont’d)
// The task for printing a character a specified number of times
class PrintChar implements Runnable {
private char charToPrint; // The character to print
private int times; // The number of times to repeat
public PrintChar(char c, int t) {
charToPrint = c;
times = t;
}
public void run(){
for (int i = 0; i < times; i++) {
System.out.print(charToPrint);
}
}
}
17
Creating and Executing Threads(cont’d)
// The task class for printing numbers from 1 to n for a given n
class PrintNum implements Runnable {
private int lastNum;
18
The Thread Class
◼The Thread class contains the constructors for
creating threads for tasks, and the methods for
controlling threads.
19
The Thread Class (cont’d)
◼You can use the yield() method to temporarily release
time for other threads.
◼Example:
public void run() {
for (int i = 1; i <= lastNum; i++) {
System.out.print(" " + i);
Thread.yield();
}
}
20
The Thread Class(cont’d)
◼The sleep(long millis) method puts the thread to sleep
for the specified time in milliseconds to allow other
threads to execute.
◼Example
public void run() {
try {
for (int i = 1; i <= lastNum; i++) {
System.out.print(" " + i);
if (i >= 50) Thread.sleep(1) ;
}
}
catch (InterruptedException ex) {
}
}
21
The Thread Class(cont’d)
◼ You can use the join() method to force one thread to wait
for another thread to finish.
◼ Example
public void run() {
Thread thread4 = new Thread new PrintChar('c', 40));
thread4.start();
try {
f or (int i = 1; i <= lastNum; i++) {
System.out.print (" " + i);
if (i == 50) thread4.join();
}
}
catch (InterruptedException ex) {
}
}
23
Thread Synchronization
◼When multiple threads share an object and that object
is modified by one or more of the threads,
indeterminate results may occur.
◼If one thread is in the process of updating a shared
object and another thread also tries to update it, it is
unclear which thread’s update takes effect.
◼This can be solved by giving only one thread at a time
exclusive access to code that manipulates the
shared object.
◼Thread synchronization, coordinates access to
shared data by multiple concurrent threads.
24
Thread Synchronization (cont’d)
◼Example – without synchronization
import java.util.concurrent.*;
public class AccountWithoutSync {
private static Account account = new Account();
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
// Create and launch 100 threads
for (int i = 0; i < 100; i++) {
executor.execute(new AddAPennyTask());
}
executor.shutdown();
// Wait until all tasks are finished
while (!executor.isTerminated()) {
}
System.out.println("What is balance? " + account.getBalance());
}
25
// A thread for adding a penny to the account
private static class AddAPennyTask implements Runnable {
public void run() {
account.deposit(1);
}
}
// An inner class for account
private static class Account {
private int balance = 0;
public int getBalance() {
return balance;
}
26
public void deposit(int amount) {
int newBalance = balance + amount;
// This delay is deliberately added to magnify the
// data-corruption problem and make it easy to see.
try {
Thread.sleep(5);
}
catch (InterruptedException ex) {
}
balance = newBalance;
}
}
}
27
28
Thread Synchronization (cont’d)
◼ A class is said to be thread-safe if an object of the class
does not cause a race condition in the presence of multiple
threads.
◼ One approach is to make Account thread-safe by adding
the keyword synchronized in the deposit method as
follows:
◼ public synchronized void deposit(double amount)
◼ A synchronized method acquires a lock before it executes.
◼ With the deposit method synchronized, the preceding
scenario cannot happen.
◼ If Task 1 enters the method, Task 2 is blocked until Task 1
finishes the method,
29
Thread Synchronization (cont’d)
30
Thread Synchronization (cont’d)
◼A synchronized instance method implicitly acquires a
lock on the instance before it executes the method.
◼Java enables you to acquire locks explicitly, which
gives you more control for coordinating threads.
◼A lock is an instance of the Lock interface, which
defines the methods for acquiring and releasing locks.
◼ lock() - Acquires the lock.
◼ unlock() - Releases the lock.
◼ newCondition() - creates any number of Condition objects,
which can be used for thread communications.
◼Example: AccountWithSyncUsingLock
31
Cooperation Among Threads
◼Thread synchronization suffices to avoid race
conditions by ensuring the mutual exclusion of
multiple threads in the critical region.
◼But, sometimes you also need a way for threads to
cooperate.
◼Conditions can be used to facilitate communications
among threads.
◼A thread can specify what to do under a certain
condition.
◼Conditions are objects created by invoking the
newCondition() method on a Lock object.
32
Cooperation Among Threads (cont’d)
◼Example: ThreadCooperation.java
33
34