Thread
Advanced Programming
SUT • Spring 2019
Contents
-
Need for multi-thread programming
-
Threads in java
-
Samples
-
Synchronization
-
synchronized
-
wait & notify
-
join
-
Program Executation
Sequential Programming
-
Up to this point, we learned sequential programming.
-
Everything in a program happens one step at a time.
-
What is wrong with this approach?
Multitasking and Multithreading
-
Multitasking refers to a computer's ability to perform multiple jobs concurrently
-
more than one program are running concurrently, e.g., UNIX
-
-
A thread is a single sequence of execution within a program
-
Multithreading refers to multiple threads of control within a single program
-
each program can run multiple threads of control within it, e.g., Web Browser
-
Concurrency vs. Parallelism
What are Threads Good For?
-
To maintain responsiveness of an application during a long running task.
-
To enable cancellation of separable tasks.
-
Some problems are intrinsically parallel.
-
To monitor status of some resource (DB).
Parallel Processing
- Multi-Processor Systems
- Multi-core CPUs
- Dual core
- Core2duo
- Corei7, corei5
- Even with no multi-core processors, Multithreading is useful
- How?
- I/O bounded tasks
- Responsive UI
- Simulated multi-threading
- How?
OS Support
-
Multi-task OS
-
Windows & Unix
-
-
Multi-thread OS
-
Single task OS
-
DOS
-
Language Support
-
Some languages have no built-in mechanism for muli-threading
-
C, C++, …
-
QT as a solution
-
-
-
OS-dependent libraries
-
pthread in linux
-
Windows API
-
-
Java has multi-threading in its core language
-
Pros and cons
-
ISA experience
-
Application Thread
-
When we execute an application:
-
The JVM creates a Thread object whose task is defined by the main() method
-
It starts the thread
-
The thread executes the statements of the program one by one until the method returns and the thread dies
-
Multiple Threads in an Application
-
Each thread has its private run-time stack
-
If two threads execute the same method, each will have its own copy of the local variables the methods uses
-
However, all threads see the same dynamic memory (heap)
-
Two different threads can act on the same object and same static fields concurrently
Creating Threads
-
There are two ways to create our own Thread object
-
Subclassing the Thread class and instantiating a new object of that class
-
Implementing the Runnable interface
-
-
In both cases the run() method should be implemented
Extending Thread
public class ThreadExample extends Thread {
public void run() {
for (int i = 1; i <= 100; i++) {
System.out.println("Thread: " + i);
}
}
}
Thread Methods
-
void start()
-
Creates a new thread and makes it runnable
-
This method can be called only once
-
-
void run()
-
The new thread begins its life inside this method
-
Thread Methods
-
sleep(int m)/sleep(int m,int n)
-
The thread sleeps for m milliseconds, plus n nanoseconds
-
-
yield()
-
Causes the currently executing thread object to temporarily pause and allow other threads to execute
-
Allow only threads of the same priority to run
-
Nothing is guaranteed for this method
-
Implementing Runnable
public class RunnableExample implements Runnable {
public void run () {
for (int i = 1; i <= 100; i++) {
System.out.println ("Runnable: " + i);
}
}
}
A Runnable Object
-
The Thread object’s run() method calls the Runnable object’s run() method
-
Allows threads to run inside any object, regardless of inheritance
Starting the Threads
public class ThreadsStartExample {
public static void main (String argv[]) {
new ThreadExample().start();
new Thread(new RunnableExample()).start();
}
}
Scheduling Threads
More Thread States
-
getState() method in Thread
Thread State Diagram
Example
class ThreadExample extends Thread {
public void run() {
MultiThreading.task("Thread");
}
}
class RunnableExample implements Runnable{
public void run() {
MultiThreading.task("Runnable");
}
}
public class MultiThreading {
public static void task(String taskName){
for(int i = 1; i <= 10; i++) {
System.out.println(taskName + ": " + i);
try {
Thread.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Running the Threads
public class Main {
public static void main(String[] args){
ThreadExample thr1 = new ThreadExample();
thr1.start();
RunnableExample run1 = new RunnableExample();
new Thread(run1).start();
ThreadExample thr2 = new ThreadExample();
thr2.start();
RunnableExample run2 = new RunnableExample();
new Thread(run2).start();
}
}
GUI Example
- Start Counting = starts counting the counter
- Stop Counting = stops counting the counter
UnresponsiveUI
startButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent evt) {
stop = false;
for (int i = 0; i < 100000; i++) {
if (stop)
break;
tfCount.setText("" + countValue);
countValue++;
}
}
});
UnresponsiveUI (2)
StopButton:
stopButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent evt) {
stop = true;
}
});
ResponsiveUI
btnStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
stop = false;
Thread t = new Thread() {
public void run() {
for (int i = 0; i < 100000; i++) {
if (stop)
break;
tfCount.setText("" + countValue);
countValue++;
try {
sleep(10);
} catch (InterruptedException ex) {}
}
}
};
t.start();
}
});
Java Scheduling
-
Thread scheduling is the mechanism used to determine how runnable threads are allocated CPU time
-
Scheduler is based on priority of threads
-
The priority of a thread: the importance of a thread to the scheduler
-
Uses fixed-priority scheduling:
-
Threads are scheduled according to their priority
-
Priority is compared with other threads in the ready queue
-
Thread Priority
-
The scheduler will lean toward running the waiting thread with the highest priority first
-
Lower-priority threads just tend to run less often
-
The exact behavior depends on the platform
-
Usually, all threads should run at the default priority
-
Trying to manipulate thread priorities is usually a mistake
Thread Priority (2)
-
Every thread has a priority
-
When a thread is created, it inherits the priority of the thread that created it
-
The priority values range from 1 to 10, in increasing priority
Thread Priority (3)
-
The priority can be adjusted subsequently using the setPriority() method
-
The priority of a thread may be obtained using getPriority()
-
Priority constants are defined:
-
MIN_PRIORITY=1
-
MAX_PRIORITY=10
-
NORM_PRIORITY=5
-
Some Notes
- Thread implementation in Java is actually based on operating system support
- Some Windows operating systems support only 7 priority levels, so different levels in Java may actually be mapped to the same operating system level
Daemon Threads
- Daemon threads are “background” threads, that provide services to other threads, e.g., the garbage collection thread
- The Java VM will not exit if non-Daemon threads are executing
- The Java VM will exit if only Daemon threads are executing
- Daemon threads die when the Java VM exits
- A thread becomes a daemon with setDaemon() method
Concurrency
Concurrency
- An object in a program can be changed by more than one thread
- Q: Is the order of changes that were preformed on the object important?
Race Condition
- A race condition – the outcome of a program is affected by the order in which the program's threads are allocated CPU time
- Two threads are simultaneously modifying a single object
- Both threads “race” to store their value
Monitors
-
Each object has a “monitor” that is a token used to determine which application thread has control of a particular object instance
-
In execution of a synchronized method (or block), access to the object monitor must be gained before the execution
-
Access to the object monitor is queued
Monitor (cont.)
-
Entering a monitor is also referred to as locking the monitor, or acquiring ownership of the monitor
-
If a thread A tries to acquire ownership of a monitor and a different thread has already entered the monitor, the current thread (A) must wait until the other thread leaves the monitor
Critical Section
-
The synchronized methods define critical sections
-
Execution of critical sections is mutually exclusive. Why?
Example
public class BankAccount {
private float balance;
public synchronized void deposit(float amount) {
balance += amount;
}
public synchronized void withdraw(float amount) {
balance -= amount;
}
}
Static Synchronized Methods
-
Marking a static method as synchronized, associates a monitor with the class itself
-
The execution of synchronized static methods of the same class is mutually exclusive.
-
Why?
-
Synchronized Statements
-
A monitor can be assigned to a block
-
It can be used to monitor access to a data element that is not an object, e.g., array
byte[] array;
void arrayShift(int count) {
synchronized(array) {
System.arraycopy (array, count,array, 0, array.size - count);
}
}
Two Identical Methods
private synchronized void g() {
h();
}
Private void g() {
synchronized(this){
h();
}
}
Join()
-
A method can wait for finishing another thread
-
Using thread.join()
Wait and Notify
-
Allows two threads to cooperate
-
Based on a single shared lock object
-
Marge put a cookie notify Homer and wait
-
Homer eat a cookie notify Marge and wait
-
The wait() Method
-
The wait() method is part of the java.lang.Object interface
-
It requires a lock on the object’s monitor to execute
-
It must be called from a synchronized method, or from a synchronized segment of code.
-
In other words: The current thread should have acquired a lock on this object before calling any of the wait methods
-
Otherwise: IllegalMonitorStateException
The wait() Method
-
wait() causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object
-
Upon call for wait(), the thread releases ownership of this monitor and waits until another thread notifies the waiting threads of the object
The wait() Method
-
wait() is also similar to yield()
-
Both take the current thread off the execution stack and force it to be rescheduled
-
-
However, wait() is not automatically put back into the scheduler queue
-
notify() must be called in order to get a thread back into the scheduler’s queue
-
notify() and notifyAll()
-
The need to the clock
-
Similar to wait() method:
-
The current thread should have acquired a lock on this object before calling notify() or notifyAll()
-
Otherwise: IllegalMonitorStateException
-
the task calling wait(), notify(), or notifyAll() must "own" (acquire) the lock for the object before it can call any of those methods.
wait() and the Lock
-
The object lock is released during the wait()
Some Notes
-
Thread-safe Classes
-
E.g, StringBuffer is thread-safe
-
public synchronized StringBuffer append(String str){…}
-
-
and StringBuilder is NOT thread-safe
-
public StringBuilder append(String str) {…}
-
-
-
Threading Problems
-
Starvation
-
Deadlock
-
Example: Producer/Consumer
-
The producer–consumer problem
-
is a classic example of a multi-process synchronization problem
-
The problem:
-
two processes, the producer and the consumer,
-
who share a common, fixed-size buffer used as a queue.
-
Title Text
Thread
By Behnam Hatami
Thread
Thread / Advanced Programming Course @ SUT, Spring 2019
- 1,277