Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
EE2E1. JAVA Programming
Lecture 8
Multi-threading
Contents
Introduction
Creating a thread – the Thread class
Starting and running threads
Thread states
Thread priorities and scheduling
Thread synchronisation
The Runnable interface
Introduction
You are used to computers (operating systems)
being multi-tasking
You can browse the web whilst editing your
Java programs!
Multi-tasking refers to an operating system running
several processes concurrently
Each process has its own completely
independent data
Multi-tasking is difficult to incorporate in
application programs requiring system
programming primitives
Java is the only commonly used programming
language that enables concurrency to be
implemented within application programs
Multi-threading
An application program can be written as a set of
threads which run concurrently (in parallel)
A thread is different from a process in that threads
share the same data
Switching between threads involves much less
overhead than switching between programs
Sharing data can lead to programming
complications (for example in reading/writing
databases)
Creating threads – the Thread class
To run a piece of code in a separate thread it is
placed in the run() method of a class which
extends Thread
class ThreadApp extends Thread
{
public void run()
{
// This code runs in a new thread
}
public static void main(String args[])
{
ThreadApp m=new ThreadApp();
m.start();
}
}
The Thread class has a start() method
which automatically calls run()
main() thread
new thread created
new thread
Example
The following simple application creates
separate threads to update a count within a
window
http://www.eee.bham.ac.uk/spannm/Java%2
0Stuff/ThreadTestApplet/ThreadTestApplet
.html
Main thread
Create counter
thread
Create counter
thread
…..
Class Counter stores the current count and a
frame to display the text
It has a a run() method which simply slowly
counts upwards within a separate thread
class Counter extends Thread
{
public Counter(LabelFrame frame)
{…}
public void run()
{..}
}
private int count=0;
private LabelFrame labelFrame;
public void run()
{
try
{
do
{
count++;
labelFrame.getPanel().setCount(count);
sleep(10);
labelFrame.repaint();
} while (true);
}
catch(InterruptedException e){}
}
public class ThreadTestFrame extends JFrame
{
private int nthreads=0;
public ThreadTestFrame()
{
Container contentPane=getContentPane();
JPanel p=new JPanel();
addButton(p,"Start Count",
new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
// Select frame colour
Counter c=new Counter(new LabelFrame(color));
c.start();
nthreads++;
}
});
contentPane.add(p,"South");
}
}
public void addButton(Container c, String title, ActionListener a)
{ // Add button to a panel }
The sleep(int t) method is a static method of
Thread which puts the currently running thread to
sleep for t milliseconds
This allows other counters running in separate
threads to resume counting
sleep() throws an exception when the thread is
interrupted by another thread wanting to run –
hence the try-catch clause
Each Counter object is created in the
actionPerformed() method of the button
attached to the outer frame (applet)
The thread is started by calling the start()
method
The number of threads started is counted
in the nthreads variable and the frame
colour selected accordingly
Thread states
A thread can exist in one of 4 states
new
The thread has just been created
runnable
The start() method has been called for
the thread and it is now ready to run
blocked
Either the sleep() method has been called
The thread has blocked on an I/O operation
The thread has called the wait() method
The thread tries to lock an object that is
locked by another thread
dead
Either the run() method for the thread has
completed or an uncaught exception has
terminated the run() method
sleep()
Done sleeping
blocked
wait()
notify()
new
start()
runnable
block on I/O
I/O complete
run() method exits
dead
Thread priorities and scheduling
Every thread has a priority which can be increased
or decreased by calling the setPriority() method
Thread.MIN_PRIORITY is the minimum
priority (defined 1)
Thread.MAX_PRIORITY is the maximum
priority (defined as 10)
When a thread is created, it is given a priority
of 5 – defined as Thread.NORM_PRIORITY
Thread scheduling
Differs depending on the operating system
Windows
UNIX, LINUX
Each thread is given a timeslice after which
it is pre-empted by another thread of higher
or equal priority
A thread can only be pre-empted by a thread
of higher priority. If one is not available, the
thread runs to completion
In both cases, lower priority threads can only run
if all higher priority threads are blocked
Runnable threads
P=5 P=5 P=3
Blocks
Blocks
Un-blocks
Blocked threads
Thread synchronisation
Threads need to share access to objects and may
update shared objects
For example multiple threads may access a
database for an online flight booking system
One thread may be updating a database entry
whilst another is reading it may lead to problems
We can synchronise threads so that they must
complete their action before another thread is
scheduled
We do this by tagging methods as synchronized
When a synchronised method is being
executed, the object is locked and no other
method can access the object until the method
completes
Unsynchronised threads
Thread 1
Thread 2
Pre-empt
Update
database
Pre-empt
Read
database
Synchronised threads
Thread 1
Thread 2
Update
database
Read
database
Example – An online seat
reservation system
Seats for a concert can be reserved through
booking agents
The processing for each booking agent runs in a
separate thread – possibly on a different processor
Each booking transaction must check seat
availability before reserving the seat
Booking
agent 1
Booking
agent 2
…..
Booking
agent n
Check availability
Reserve seat
Check
availability
Reserve seat
Check availability
Reserve seat
Seat reservation
database
Pseudo-code for booking a seat
if seat n is available
book seat n;
Code not atomic
For an unsynchronised thread it can be preempted by another thread after the if statement
The thread might think the seat is available but
it then might be booked by the pre-empting
thread
The seat will be double booked
http://www.eee.bham.ac.uk/spannm/Java%20Stuff
/SeatBookingApplet/SeatBookingApplet.html
Unsynchronised threads
Booking agent 1
Booking agent 2
check availability
pre-empted
check availability
re-schedule
book seat
book seat
2 main classes
SeatBookings
Contains the seat booking information (just a
simple array)
Contains isAvailable() and bookSeat()
methods which access the seat booking
information
BookingAgent
Extends Thread and thus contains a run()
method
Contains a reference to a SeatBookings
object which is thus a shared object between
all of the BookingAgent objects
The code is as follows (code to output to frames
has been omitted)
class SeatBookings
{
private int[] seats;
public SeatBookings(int[] s)
{
seats=s;
}
public boolean isAvailable(int seatno)
{
return (seats[seatno]==0);
}
public void bookSeat(int seatno)
{
if (isAvailable(seatno))
seats[seatno]++;
}
}
public boolean doubleBooked(int seatno)
{
return (seats[seatno]>1);
}
class BookingAgent extends Thread
{
private SeatBookings sb;
// shared object
public BookingAgent(SeatBookings s)
{
sb=s;
}
public void run()
{
do
{
int seatno=(int)(Math.random()*20000);
sb.bookSeat(seatno);
if (sb.doubleBooked(seatno))
// generate a warning dialog
}
}
} while (true);
We can synchronise the threads by tagging
the SeatBookings.bookSeat() method as
synchronized
The SeatBookings object is then locked
by the thread which has current access
Booking
agent 1
locked
Booking
agent 2
locked out
SeatBookings object
Synchronised threads
Booking agent 1
Booking agent 2
check availability
book seat
check availability
book seat
check availability
book seat
Simple change to code
class SeatBookings
{
.
.
}
public synchronized void bookSeat(int seatno)
{
…
}
.
.
No double booking then takes place
http://www.eee.bham.ac.uk/spannm/Java%20
Stuff/SeatBooking%20SynchApplet/SeatBook
ingSynchApplet.html
The Runnable interface
So far, to develop classes which support multithreading we have extended the Thread class and
overwritten the run() method
This causes problems if the class is already
extended from another class
Java doesn’t support multiple inheritance
SuperClass
MyClass
Thread
This is generally a problem if we want outer
containers (JFrame or JApplet) objects to support
multi-threading
The simple solution is to make our class
implement the Runnable interface
It would then need to implement a run()
method in the usual way
class myClass extends superClass implements Runnable
{
…
public void run() {…}
}
A thread is created and MyClass.run()
started as follows :
MyClass myObject=new Myclass();
Thread t=new Thread(myObject);
t.start();
The call to Thread(Runnable r) creates a
thread
Calling Thread.start() then automatically
calls the run() method of the Runnable
object
Example – a counter applet
We will create an applet which has 2 buttons
Start Count
Reset Count
The thread to do the counting must run in a
separated thread to the one which handles button
presses
Swing programs create an event dispatch thread
which handles all the events generated by the
program (including window events for
repainting graphics)
Main thread
Event dispatch
thread
Counting
thread
Construct applet
container
show container
exits
Start button
pressed
Start
counting …
Reset count
Reset button
pressed
The following applet doesn’t use a separate thread
to do the counting
Button press events or repainting events can’t
be handled once counting begins
http://www.eee.bham.ac.uk/spannm/Java%2
0Stuff/CounterApplet/CounterApplet.html
The following applet generates a separate
thread for the counter
http://www.eee.bham.ac.uk/spannm/Java%2
0Stuff/RunnableTestApplet/RunnableTestAp
plet.html
public class RunnableTestApplet extends JApplet implements
Runnable
{
public void init()
{
// Generate outer container …
addButton(p,"Start Count",
new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
startCount();
}
});
addButton(p,"Reset Count",
new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
resetCount();
}
});
}
// Add buttons to container …
public void startCount()
{
runner=new Thread(this);
runner.start();
}
public void resetCount()
{
runner.interrupt();
count=0;
// repaint frame
}
public void run()
{
while (!Thread.interrupted())
{
count++;
// repaint frame
}
}
private Thread runner;
} // end of class RunnableTestApplet
And finally…..
Multi-threading is complex
Make sure you understand the code for the first example
we looked at
Run the applet from my web site and scrutinize the code
Multi-threading is the basis of many applications and, as
we have seen, particularly crucial in graphical/event driven
programming
We have only scratched the surface. For an excellent and
thorough description of threading see
www.albahari.com/threading
In the last lab exercise, you will have the opportunity to
write a multi-threading server for a network-based game!