0% found this document useful (0 votes)
11 views28 pages

Lec10 - Java Multithreading

This document provides an overview of multithreading programming in Java, highlighting its ability to execute multiple tasks concurrently. It introduces key concepts such as threads, the Thread class, and the Runnable interface, along with practical examples of creating and managing threads. Additionally, it discusses advanced topics like thread pools, race conditions, and the use of the Executor framework for efficient task management.

Uploaded by

abdklaib2333
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views28 pages

Lec10 - Java Multithreading

This document provides an overview of multithreading programming in Java, highlighting its ability to execute multiple tasks concurrently. It introduces key concepts such as threads, the Thread class, and the Runnable interface, along with practical examples of creating and managing threads. Additionally, it discusses advanced topics like thread pools, race conditions, and the use of the Executor framework for efficient task management.

Uploaded by

abdklaib2333
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Multithreading Programming in Java

Instructor: Dr. Fahed Jubair


Computer Engineering Department
University of Jordan
1098 Chapter 30 Multithreading and Parallel Programming

30.1 Introduction
Multithreading enables multiple tasks in a program to be executed concurrently.
Key
Point One of the powerful features of Java is its built-in support for multithreading—the concurrent
multithreading

Motivation
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 multithreading programs can be developed in Java.

• Multithreading
30.2 Thread enables multiple tasks in a program to be executed concurrently
Concepts
• A thread
Key
A is the flow
program of execution,
may consist from
of many tasks that beginning
can run concurrently. to end,is the
A thread of flow
a specific task
Point of execution, from beginning to end, of a task.
thread
• The operating system is responsible for scheduling and allocating resources to
A thread provides the mechanism for running a task. With Java, you can launch multiple
task threads threads from a program concurrently. These threads can be executed simultaneously in multi-
processor systems, as shown in Figure 30.1a.

Thread 1 Thread 1

Thread 2 Thread 2

Thread 3 Thread 3

(a) (b)
Multiple threads running Multiple threads share a single
FIGURE 30.1on (a) Here multiple
multiple CPUs threads are running onCPU
multiple
(aka. CPUs. (b) Here multiple
time sharing)
threads share a single CPU.
© All rights reserved.
In single-processor systems, as shown in Figure 30.1b, the multiple threads share CPU
time sharing time, known as time sharing, and the operating system is responsible for scheduling and allo-
cating resources to them. This arrangement is practical because most of the time the CPU is
idle. It does nothing, for example, while waiting for the user to enter data.
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
Multithreading in Java
30.3 Creating Tasks and Threads 1099

[Link] TaskClass // Client class


public class Client {
...
// Custom task class public void someMethod() {
public class TaskClass implements Runnable { ...
... // Create an instance of TaskClass
public TaskClass(...) { TaskClass task = new TaskClass(...);
...
} // Create a thread
Thread thread = new Thread(task);
// Implement the run method in Runnable
public void run() { // Start a thread
// Tell system how to run custom thread [Link]();
... ...
} }
... ...
} }

(a) (b)

FIGURE 30.2 Define a task class by implementing the Runnable interface.

© All rights
Once you have defined a TaskClass, you can create reserved.
a task using its constructor. For
example,
TaskClass task = new TaskClass(...);

A task must be executed in a thread. The Thread class contains the constructors for cre- Thread class
ating threads and many useful methods for controlling threads. To create a thread for a create a task
Startup Example

public class TaskThreadDemo { class PrintChar implements Runnable { class PrintNum implements Runnable {
public static void main(String[] args) { private char charToPrint; // The character to print private int lastNum;
// Create tasks private int times; // The times to repeat public PrintNum(int n) {
Runnable printA = new PrintChar('a', 100); public PrintChar(char c, int t) { lastNum = n;
Runnable printB = new PrintChar('b', 100); charToPrint = c; }
Runnable print100 = new PrintNum(100); times = t;
} @Override
// Create threads public void run() {
Thread thread1 = new Thread(printA); @Override for (int i = 1; i <= lastNum; i++) {
Thread thread2 = new Thread(printB); public void run() { [Link](" " + i);
Thread thread3 = new Thread(print100); for (int i = 0; i < times; i++) { }
[Link](charToPrint); }
// Start threads } }
[Link](); }
[Link](); }
[Link]();
}
}

© All rights reserved.


Busy-Wait Loop
public class TaskThreadDemo {
public static void main(String[] args) {
// Create tasks
Runnable printA = new PrintChar('a', 100);
Runnable printB = new PrintChar('b', 100);
Runnable print100 = new PrintNum(100);

// Create threads
Thread thread1 = new Thread(printA);
Thread thread2 = new Thread(printB);
Thread thread3 = new Thread(print100);

// Start threads
[Link]();
[Link]();
[Link](); The main process will get stuck here till thread1 terminates
The main process will get stuck here till thread2 terminates
while( [Link]() ) { }
while( [Link]() ) { } The main process will get stuck here till thread3 terminates
while( [Link]() ) { }
}
}
© All rights reserved.
1102 Chapter 30 Multithreading and Parallel Programming

The
30.4 The Thread
Thread Class Class
The Thread class contains the constructors for creating threads for tasks and the
Key
Point methods for controlling threads.
• The Thread class contains
Figure 30.4 shows the constructors
the class for creating
diagram for the Thread class. threads for tasks
and methods for controlling threads.
«interface»
[Link]

[Link]

+Thread() Creates an empty thread.


+Thread(task: Runnable) Creates a thread for a specified task.
+start(): void Starts the thread that causes the run() method to be invoked by the JVM.
+isAlive(): boolean Tests whether the thread is currently running.
+setPriority(p: int): void Sets priority p (ranging from 1 to 10) for this thread.
+join(): void Waits for this thread to finish.
+sleep(millis: long): void Puts a thread to sleep for a specified time in milliseconds.
+yield(): void Causes a thread to pause temporarily and allow other threads to execute.
+interrupt(): void Interrupts this thread.
© All rights reserved.

FIGURE 30.4 The Thread class contains the methods for controlling threads.

Note
Since the Thread class implements Runnable, you could define a class that extends
Thread and implements the run method, as shown in Figure 30.5a, and then create
+sleep(millis: long): void Puts a thread to sleep for a specified time in milliseconds.
+yield(): void Causes a thread to pause temporarily and allow other threads to execute.
+interrupt(): void Interrupts this thread.

FIGURE 30.4 The Thread class contains the methods for controlling threads.

Note

Alternative Method For Running Threads


Since the Thread class implements Runnable, you could define a class that extends
Thread and implements the run method, as shown in Figure 30.5a, and then create
an object from the class and invoke its start method in a client program to start the
separating task from thread thread, as shown in Figure 30.5b.

[Link] CustomThread // Client class


public class Client {
...
// Custom thread class public void someMethod() {
public class CustomThread extends Thread { ...
... // Create a thread
public CustomThread(...) { CustomThread thread1 = new CustomThread(...);
...
} // Start a thread
[Link]();
...
// Override the run method in Runnable
public void run() { // Create another thread
// Tell system how to perform this task CustomThread thread2 = new CustomThread(...);
...
} // Start a thread
... [Link]();
} }
...
}

(a) (b)
© All rights reserved.
FIGURE 30.5 Define a thread class by extending the Thread class.
Example
Thread Test
// output
Creating Thread-1
Creating Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

© All rights reserved.


Sleep
● Sometimes a thread has nothing to do for some period of time
● It can relinquish its time on a processor by using sleep(ms)
● This can be useful:
○ to simulate the passage of time

○ to let other processes work while this process waits

© All rights reserved.


Task Parallelism

Thread 0 for ( i = 0; i < n; i++)


Sum [ i ] = A[ i ] + B[ i ]

for ( i = 0; i < n; i++)


Sum [ i ] = A[ i ] + B[ i ]
Diff [ i ] = A[ i ] − B[ i ]

for ( i = 0; i < n; i++)


Thread 1 Diff [ i ] = A[ i ] − B[ i ]

© All Right Reserved.


Data Parallelism

for ( i = 0; i < n/2; i++)


Thread 0 Sum [ i ] = A[ i ] + B[ i ]
Diff [ i ] = A[ i ] − B[ i ]

for ( i = 0; i < n; i++)


Sum [ i ] = A[ i ] + B[ i ]
Diff [ i ] = A[ i ] − B[ i ]
for ( i = n/2; i < n; i++)
Thread 1 Sum [ i ] = A[ i ] + B[ i ]
Diff [ i ] = A[ i ] − B[ i ]

© All Right Reserved.


Exercise

• Use multithreading to perform


the computation inside this loop
in parallel using two threads
• Use busy-wait loops if you need
to force waiting for thread
completion

© All rights reserved.


Join
● Busy/wait loops are inefficient (why?)
● To wait on another thread to complete, use the
join() method instead
● Forces the waiting thread to relinquish the
processor and go to sleep
● Wake up periodically to check for completion

● Join() method throws the checked exception


InterruptedException

Redo previous exercise while using Join method


© All rights reserved.
Anonymous Classes
Employee p1 = new Employee ("Mike");
Employee p2 = new Employee ("Jane"); • Java allows on-the-fly one-
Employee p3 = new Employee ("Ali"); time subclasses to be created
Employee p4 = new Employee ("Basim");
Anonymous
in place of base classes or
comparator object interfaces
Set <Employee> party = new TreeSet<> (
new Comparator <Employee>(){
• There are referred to as
public int compare (Employee a, Employee b) {
anonymous classes because
return [Link] ().compareTo ([Link] ()); they have no names
}
}); • Anonymous classes are
[Link] (p1); convenient for declaring on-
[Link] (p2);
[Link] (p3);
the-fly tasks
[Link] (p4);
[Link] (party);

© All rights reserved.


Anonymous
Tasks Demo

Redo previous exercise while using anonymous classes


© All rights reserved.
Thread Pool
• In many programs, many tasks can be executed in parallel
• Creating a thread for each task if not efficient for a large number of tasks
because the large number of threads will oversubscribe the system
• Java provides a mechanism for creating a pool of specific number of
threads for executing large number of tasks
• A thread pool keeps all tasks in a waiting queue
• Each thread starts by executing a task from the queue, when done, it
grabs another task, and so on

© All rights reserved.


The Executor and ExecutorService Interfaces
This approach is convenient for a single task execution, but it is not efficient for a large
30.6 Thread Pools 1107

number of tasks because you have to create a thread for each task. Starting a new thread for
• Java provides the Executor interface for executing tasks in a thread pool
each task could limit throughput and cause poor performance. Using a thread pool is an ideal
way to manage the number of tasks executing concurrently. Java provides the Executor
and the ExecutorService interface for managing and controlling tasks
interface for executing tasks in a thread pool and the ExecutorService interface for man-
aging and controlling tasks. ExecutorService is a subinterface of Executor, as shown in
• ExecutorService is a subinterface of Executor
Figure 30.7.

«interface»
[Link]

+execute(Runnable object): void Executes the runnable task.

«interface»
[Link]

+shutdown(): void Shuts down the executor, but allows the tasks in the executor
to complete. Once shut down, it cannot accept new tasks.
+shutdownNow(): List<Runnable> Shuts down the executor immediately even though there are
unfinished threads in the pool. Returns a list of unfinished tasks.
+isShutdown(): boolean Returns true if the executor has been shut down.
+isTerminated(): boolean Returns truereserved.
© All rights if all tasks in the pool are terminated.

FIGURE 30.7 The Executor interface executes threads, and the ExecutorService subinterface manages threads.

To create an Executor object, use the static methods in the Executors class, as shown
in Figure 30.8. The newFixedThreadPool(int) method creates a fixed number of threads
in a pool. If a thread completes executing a task, it can be reused to execute another task. If
The Executers Class
• The Executers class has static methods useful for creating an Executor object
• There are two static methods for creating two different types of thread pools:
• newFixedThreadPool(int)
• Creates a fixed number of threads in a pool
• If a thread completes executing a task, it can be reused to execute another task
• If a thread terminates due to a failure prior to shutdown, a new thread will be created to
replace it if all the threads in the pool are not idle and there are tasks waiting for execution
• newCachedThreadPool()
• Creates a new thread if all the threads in the pool are not idle and there are tasks waiting for
execution
• A thread in a cached pool will be terminated if it has not been used for 60 seconds
• Efficient for many short tasks

© All rights reserved.


Example
Executor Demo

© All rights reserved.


Race Condition
• During concurrent execution, multiple threads may share data
• Reading and writing to shared data by multiple threads simultaneously
may lead to inconsistent update of data (i.e., threads may incorrectly
override each other)
• Such a situation when data is corrupted due to concurrent thread
execution is called a race condition
• Race conditions cause incorrectness in concurrent execution

© All rights reserved.


import [Link].*;
Example: Race Condition Demo
public class AccountWithoutSync {
private static Account account = new Account();
// An inner class for account
private static class Account {
public static void main(String[] args) {
private int balance = 0;
ExecutorService executor = [Link]();
public int getBalance() {
// Create and launch 100 threads
return balance;
for (int i = 0; i < 100; i++) {
}
[Link](new AddAPennyTask());
}
public void deposit(int amount) {
int newBalance = balance + amount;
[Link]();
// This delay is deliberately added to magnify the
// Wait until all tasks are finished
// race condition problem and make it easy to see.
while (![Link]()) { }
try {
[Link](5);
[Link]("What is balance? " + [Link]());
}
}
catch (InterruptedException ex) {
}
// A thread for adding a penny to the account
private static class AddAPennyTask implements Runnable {
balance = newBalance;
public void run() {
}
[Link](1);
}
}
} reserved.
© All rights
}
Thread Synchronization and Critical Regions
• Thread synchronization is a mechanism for controlling access to shared data
between multiple threads so that race conditions are avoided
• Example of a thread synchronization mechanism is a critical region, which is a
region of code that allows one thread to execute this region at a time
• Critical regions are typically used whenever a specific region in the code needs
to be executed serially

© All rights reserved.


The Synchronized Keyword
• In Java, the synchronized keyword is provided to specify a critical regions
• Using the synchronized keyword with a method will make this entire
method executed as a critical region
• Example: in the previous example, use “public synchronized void deposit(int amount)” to
declare the deposit method as a critical region
• Using the synchronized keyword with statements make them executed
inside a critical region
• Example, in the previous example, write the below code to make a critical region
synchronized (account) {
[Link](1);
}

© All rights reserved.


Synchronization Using Locks
• Locks are mechanisms for implementing critical regions
• Only a thread that has the lock is allowed to enter and
execute the critical region Acquire a lock

• The synchronized keyword uses the lock/unlock


Execute the critical region
mechanism for implementing a critical region
• However, Java also enables acquiring and releasing Release the lock
locks explicitly to allow users more thread control

© All rights reserved.


The Lock Interface and The ReentrantLock Class
• ReentrantLock is a concrete implementation of Lock for creating
mutually exclusive locks 30.8 Synchronization Using Locks 1113

«interface»
[Link]

+lock(): void Acquires the lock.


+unlock(): void Releases the lock.
+newCondition(): Condition Returns a new Condition instance that is bound to this
Lock instance.

[Link]
+ReentrantLock() Same as ReentrantLock(false).
+ReentrantLock(fair: boolean) Creates a lock with the given fairness policy. When the
fairness is true, the longest-waiting thread will get the
lock. Otherwise, there is no particular access order.

© All rights reserved.


FIGURE 30.13 The ReentrantLock class implements the Lock interface to represent a lock.

ReentrantLock is a concrete implementation of Lock for creating mutually exclusive


locks. You can create a lock with the specified fairness policy. True fairness policies guar- fairness policy
antee that the longest-waiting thread will obtain the lock first. False fairness policies grant a
import [Link].*;
import [Link].*;
Example: Lock/Unlock Demo
// An inner class for account
public class AccountWithSyncUsingLock {
public static class Account {
private static Account account = new Account();
private static Lock lock = new ReentrantLock(); // Create a lock
private int balance = 0;
public static void main(String[] args) {
ExecutorService executor = [Link](); public int getBalance() {
return balance;
// Create and launch 100 threads
}
for (int i = 0; i < 100; i++) {
[Link](new AddAPennyTask()); public void deposit(int amount) {
}
[Link](); // Acquire the lock
[Link]();
try {
int newBalance = balance + amount;
// Wait until all tasks are finished
[Link](5);
while (![Link]()) { }
balance = newBalance;
}
[Link]("What is balance ? " + [Link]());
catch (InterruptedException ex) {
}
}
finally {
// A thread for adding a penny to the account [Link](); // Release the lock
public static class AddAPennyTask implements Runnable {
}
public void run() {
}
[Link](1);
}
} }
© All rights reserved.
}
Exercise

• Parallelize the summation step


• Use four threads

© All rights reserved.


Summary: Thread States

NEW
start()
timer expires
timer expires interrupt
interrupt thread dies
notify/notifyAll RUNNABLE lock obtained

WAITING* scheduled timeout BLOCKED

sleep()
RUNNING lock unavailable
join()
run() returns

DEAD
[Link]()
© All rights reserved.

You might also like