Chapter 5 - MultiThreading
Chapter 5 - MultiThreading
Chapter 5 - MultiThreading
2
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.
3
Thread Concepts
A multi-threaded program contains two or more parts that
can run concurrently and each part can handle a different
task at the same time making optimal use of the available
resources specially when your computer has multiple
CPUs.
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.
7
Process vs. Threads
Process:
A process runs independently and isolated of other
processes.
It cannot directly access shared data in other processes.
The resources of the process are allocated to it via the
operating system, e.g. memory and CPU time.
Threads:
Threads are so called lightweight processes which have their
own call stack but an 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(), It is also referred to
as a born thread.
Runnable – thread can execute, after a newly born thread is
started, the thread becomes runnable. A thread in this state is
considered to be executing its task.
Blocked – thread waiting for event (I/O, etc.)
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 – 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
public class HelloThread implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
13
Creating and Executing Threads(cont’d)
Example 2
public class PrimeRun implements Runnable{
String msg;
PrimeRun (String mg)
{
msg=mg;
}
public void run()
{
for(int i=0;i<=5;i++)
{
System.out.println("Run method: "+msg);
}
}
14
Creating and Executing Threads(cont’d)
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 Pools
You learned how to create a thread to run a task like
this:
Runnable task = new TaskClass(task);
new Thread(task).start();
24
Thread Pool (cont’d)
A thread pool is ideal to manage the number of tasks
executing concurrently.
Java provides the Executor interface for executing
tasks in a thread pool and the ExecutorService
interface for managing and controlling tasks.
To create an Executor object, use the static methods
newFixedThreadPool(int).
If a thread completes executing a task, it can be
reused to execute another task.
ExecutorExample.java
25
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.
26
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());
}
27
// 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;
}
28
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;
}
}
}
29
30
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,
31
Thread Synchronization (cont’d)
32
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
33
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.
34
Cooperation Among Threads (cont’d)
Example: ThreadCooperation.java
35
36