Sei sulla pagina 1di 41

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 runnable
start()
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
Each thread is given a timeslice after which
it is pre-empted by another thread of higher
or equal priority
UNIX, LINUX
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 Blocked threads

P=5 P=5 P=3

Blocks

Blocks

Un-blocks
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 Read
database database

Pre-empt
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 Booking
agent 2
.. Booking
agent n
agent 1

Check availability
Reserve seat
Check
availability Check availability
Reserve seat 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 pre-
empted 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 Booking
agent 1 agent 2

locked 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 multi-
threading we have extended the Thread class and
overwritten the run() method
This causes problems if the class is already
extended from another class
Java doesnt support multiple inheritance

SuperClass Thread

MyClass
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 Counting
thread thread

Construct applet
container

show container

Start button Start


pressed counting
exits
Reset count
Reset button
pressed
The following applet doesnt use a separate thread
to do the counting
Button press events or repainting events cant

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!

Potrebbero piacerti anche