37
G52CON: Concepts of Concurrency Lecture 2 Processes & Threads Chris Greenhalgh School of Computer Science [email protected]

G52CON: Concepts of Concurrency Lecture 2 Processes & Threads

  • Upload
    ayame

  • View
    57

  • Download
    1

Embed Size (px)

DESCRIPTION

G52CON: Concepts of Concurrency Lecture 2 Processes & Threads. Chris Greenhalgh School of Computer Science [email protected]. Outline of this lecture. Java implementations of concurrency process and threads a simple ParticleApplet example ways of creating Thread objects in Java: - PowerPoint PPT Presentation

Citation preview

  • G52CON:Concepts of Concurrency

    Lecture 2 Processes & ThreadsChris GreenhalghSchool of Computer [email protected]

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Outline of this lectureJava implementations of concurrency

    process and threads

    a simple ParticleApplet example

    ways of creating Thread objects in Java:

    extending the Thread class; and

    implementing the Runnable interface

    the lifecycle of a Thread:

    starting a new Thread,

    while the Thread is running; and

    shutting it down

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Implementations of ConcurrencyWe can distinguish two main types of implementations of concurrency:

    shared memory: the execution of concurrent processes by running them on one or more processors all of which access a shared memory processes communicate by reading and writing shared memory locations; and

    distributed processing: the execution of concurrent processes by running them on separate processors which dont share memoryprocesses communicate by message passing.

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Java Implementations of ConcurrencyJava supports both shared memory and distributed processing implementations of concurrency:

    shared memory: multiple user threads in a single Java Virtual Machinethreads communicate by reading and writing shared memory locations; and

    distributed processing: via the java.net and java.rmi packagesthreads in different JVMs communicate by message passing or (remote procedure call)

    G52CON covers both approaches

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007, Chris Greenhalgh, 2010G52CON Lecture 2: Processes & Threads*Processes and ThreadsA process is any thread of execution or control, e.g.:

    part of a concurrent program (lightweight process)

    programs running in different address spaces on the same processor (heavyweight or OS processes; default meaning)

    running on a different processor or on a different computer

    A thread is a process which forms part of a concurrent programthreads execute within a shared address spacea Java thread is a lightweight process running within a JVMA JVM is generally run as a heavyweight or OS process

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Threads in JavaA thread is a single sequential flow of control within a Java program.

    Within the JVM, the threads comprising a Java program are represented by instances of the Thread class.Thread AThread B

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*RunnableThread lifecycleNew ThreadDeadNot runnableRunningyieldwaitnotifysleeptimeoutblocked on I/OI/O completesstartreturn

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007 Chris Greenhalgh, 2010G52CON Lecture 2: Processes & Threads*A Simple Example: ParticleAppletParticleApplet creates n Particle objects, sets each particle in autonomous continuous motion, and periodically updates the display to show their current positions:

    each Particle runs in its own Java Thread which computes the position of the particle; and

    an additional ParticleCanvas Thread periodically checks the positions of the particles and draws them on the screen.

    in this example there are at least 12 threads and possibly more, depending on how the browser handles applets.

    http://www.cs.nott.ac.uk/~cmg/G52CON/ParticleAppletA.htm

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*ParticleAppletThere are three classes:

    Particle: represents the position and behaviour of a particle and can draw the particle at its current position;

    ParticleCanvas: provides a drawing area for the Particles, and periodically asks the Particles to draw themselves; and

    ParticleApplet: creates the Particles and the canvas and sets the Particles in motion.

    See also Lea (2000), chapter 1 for an alternative implementation.

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*RunnableThread lifecycle: creationNew ThreadDeadNot runnableRunningyieldwaitnotifysleeptimeoutblocked on I/OI/O completesstartreturn

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Creating ThreadsThere are two ways to create a thread:

    extending the Thread class and overriding its run() method; or

    defining a class which implements the Runnable interface and its run() method

    public interface java.lang.Runnable { void run();}

    and passing the Runnable object to the Thread constructor.

    The Thread class implements the Runnable interface.

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Extending the Thread classclass Particle extends Thread { protected int x, y; protected final random rng = new Random(this.hashCode());

    // constructor etc

    public void run() { try { for(;;) { move(); sleep(100); } } catch (InterruptedException e) { return; } } // other methods ...

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Particle class continued

    public synchronized void move() { x += (rng.nextInt() % 10); y += (rng.nextInt() % 10); }

    public void draw(Graphics g) { int lx, ly; synchronized(this) { lx = x; ly = y; } g.drawRect(lx, ly, 10, 10); }}

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Implementing Runnableclass ParticleCanvas extends Canvas implements Runnable { private Particle[] particles = new Particle[0];

    // constructor etc ...

    public void run() { try { for(;;) { repaint(); Thread.sleep(100); } } catch (InterruptedException e) { return; } }

    // other methods ...

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*ParticleCanvas class continued

    protected synchronized void getParticles() { return particles; }

    // called by Canvas.repaint(); public void paint(Graphics g) { Particle[] ps = getParticles();

    for (int i = 0; i < ps.length(); i++) ps[i].draw(g); }}

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Particle threadspublic class ParticleAppletA extends Applet {

    protected final ParticleCanvas canvas = new ParticleCanvas(400); protected Particle[] particles; // null when not running protected Thread canvasThread; // ParticleApplet start method public synchronized void start() {int n = 10; // just for demo

    if (particles == null) { // bypass if already started particles = new Particle[n]; for (int i = 0; i < n; ++i) {particles[i] = new Particle(200, 200);particles[i].setName("Particle Thread " + i);particles[i].start(); } canvas.setParticles(particles); // continued ...

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*ParticleCanvas threadpublic class ParticleAppletA extends Applet {

    protected final ParticleCanvas canvas = new ParticleCanvas(400); protected Particle[] particles; // null when not running protected Thread canvasThread;

    // ParticleApplet start method ... public synchronized void start() {int n = 10; // just for demo

    if (particles == null) { // bypass if already started

    // code to start particles omitted canvasThread = new Thread(canvas); canvasThread.setName("Canvas Thread"); canvasThread.start();} }

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*RunnableThread lifecycle: runningNew ThreadDeadNot runnableRunningyieldwaitnotifysleeptimeoutblocked on I/OI/O completesstartreturn

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Particle.run()class Particle extends Thread {

    // fields, constructor etc

    public void run() { try { for(;;) { move(); sleep(100); } } catch (InterruptedException e) { return; } }

    // other methods }

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Particle threads...

    G52CON Lecture 2: Processes & Threads

  • Calling run() (wrong!) Chris Greenhalgh, 2010G52CON Lecture 2: Processes & Threads*

    G52CON Lecture 2: Processes & Threads

  • Calling start()(right!) Chris Greenhalgh, 2010G52CON Lecture 2: Processes & Threads*

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*ParticleCanvas.run()class ParticleCanvas extends Canvas implements Runnable {

    // fields, constructor etc

    public void run() { try { for(;;) { repaint(); Thread.sleep(100); } } catch (InterruptedException e) { return; } }

    // other methods }

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007, Chris Greenhalgh, 2010G52CON Lecture 2: Processes & Threads*ParticleCanvas thread (and AWT event thread)paint() { particles[0].draw particles[1].draw . . .

    particles[9].draw }...particles[1]move();sleep(100);

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*RunnableThread lifecycle: not runnableNew ThreadDeadNot runnableRunningyieldwaitnotifysleeptimeoutblocked on I/OI/O completesstartreturn

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*The not runnable stateA running Thread becomes not runnable when:

    it calls sleep() to tell the scheduler that it no longer wants to run;

    it blocks for I/O; or

    it blocks on entry to a synchronized block/method or in wait()for condition synchronisation.

    It blocks waiting to join() another thread (when that thread finishes)

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Examples of not runnableParticle threads become not runnable when they sleep()

    the ParticleCanvas thread also becomes not runnable when it calls sleep()

    (depending what else is happening in the Java windowing system it may also be delayed while calling repaint())

    well return to wait(), condition synchronisation and join() in later lectures

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Scheduling methodsThe Thread class provides the following static scheduling methods:

    sleep(long msecs): causes the current thread to suspend for at least msecs milliseconds.

    yield(): requests that the JVM to run any other runnable but non-running thread rather than the current thread.

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Thread prioritiesThreads have priorities which heuristically influence schedulers:

    each thread has a priority in the range Thread.MIN_PRIORITY to Thread.MAX_PRIORITYby default, each new thread has the same priority as the thread that created it---the initial thread associated with a main method by default has priority Thread.NORM_PRIORITYthe current priority of a thread can be accessed by the method getPriority and set via the method setPriority.

    When there are more runnable threads than CPUs, a scheduler is generally biased in favour of threads with higher priorities.

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*RunnableThread lifecycle: cancellationNew ThreadDeadNot runnableRunningyieldwaitnotifysleeptimeoutblocked on I/OI/O completesstartreturn

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Thread terminationA thread terminates when its run() method completes:

    either by returning normally; or

    by throwing an unchecked exception (RuntimeException, Error or one of their subclasses)

    Threads are not restartableinvoking start() more than once results in an InvalidThreadStateException.

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Thread cancellationThere are several ways to get a thread to stop:

    when the threads run() method returns;

    call Thread.stop() --- this is a bad idea, as it doesnt allow the thread to clean up before it dies; or

    interrupt() the thread.

    A multi-threaded program will continue to run until its last (non-daemon) thread terminates.

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Interrupting a ThreadEach Thread object has an associated boolean interruption status:

    interrupt(): sets a running threads interrupted status to true

    isInterrupted(): returns true if the thread has been interrupted by interrupt()

    A thread can periodically check its interrupted status, and if it is true, clean up and exit.

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007,Chris Greenhalgh, 2010G52CON Lecture 2: Processes & Threads*Thread (checked) exceptionsThreads which are blocked in calls wait() and sleep() (etc.) arent runnable, and cant check the value of the interrupted flag

    interrupting a thread which is waiting or sleeping aborts that operation and throws an InterruptedException.(if the interrupt flag is set before entering sleep/etc it immediately throws an InterruptedException)synchronized [for wait] try { wait()|sleep() } catch (InterruptedException e) { // clean up and return (interrupt flag now clear) }

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Stopping the ParticleApplet// ParticleApplet stop method (not Thread.stop) public synchronized void stop() { // Bypass if already stopped if (particles != null) { for (int i = 0; i < particles.length; ++i) particles[i].interrupt(); particles = null; canvasThread.interrupt(); canvasThread = null; }}

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Stopping the Particles// Particle run method

    public void run() { try { for(;;) { move(); sleep(100); } } catch (InterruptedException e) { return; }}

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*The Next LectureSynchronisation

    Suggested reading:

    Andrews (2000), chapter 2, sections 2.1, chapter 3, section 3.1;

    Ben-Ari (1982), chapter 2.

    G52CON Lecture 2: Processes & Threads

  • Brian Logan 2007G52CON Lecture 2: Processes & Threads*Anonymous classes// An alternative implementation (see Lea (2000), Chapter 1)protected Thread makeThread(final Particle p) { Runnable runloop = new Runnable() { public void run() { try { for(;;) { p.move(); canvas.repaint(); Thread.sleep(100); } } catch (InterruptedException e) { return; } } }; return new Thread(runloop); }

    G52CON Lecture 2: Processes & Threads

    *Summary of this lectureIn this lecture, well look at processes and threads in Java, so that we have concrete examples to think about when discussing processes in future lectures.

    The aim is not to turn you into expert Java programmers: the aim of the course is to try to teach you some of the basics of concurrency so that you can apply them in whichever language happens to be fashionable in 5 years time.*In this lecture, we shall look at the toy applet I showed you in the last lecture.

    The applet is based on an example taken from Leas book Concurrent Programming in Java:

    we will begin by looking at what a thread iswe will then look at the two ways you can create Thread objects in Java: extending the Thread class and implementing the Runnable interface.we will then look at the lifecycle of a Thread: starting a new Thread, while the Thread is running, and finally shutting it down. This will introduce most of the ideas that are covered in more detail in the rest of the course.

    If this material is not familiar, now is a good time to get to grips with itin subsequent lectures Ill assume that you know this.

    *In the last lecture, I said that there are two main ways in which we can implement concurrent programs :

    shared memory: the execution of concurrent processes by running them on one or more processors, all of which access a shared memoryprocesses communicate by reading and writing shared memory locations; and

    distributed processing: the execution of concurrent processes by running them on separate processors which communicate by message passing.

    The techniques and algorithms differ depending on which approach we use, and well look at both approaches in the course.*Java supports both shared memory and distributed processing implementations of concurrency:

    shared memory: Java has built-in support for shared memory concurrency and supports multiple user threads in a single Java Virtual Machinethreads obviously share memory (since they are running in the same JVM) and communicate by reading and writing shared memory locations (i.e., fields in objects); and

    distributed processing: Java also provides support for distributed processing via the java.net and java.rmi packageshere threads in different JVMs communicate by message passing or remote procedure calls which are built on top of message passing.

    Well cover shared memory approaches over the next few weeks before moving on to distributed processing approaches. *Before going on, I would like to clarify the difference between a process and a thread.

    Definition of process and thread which are consistent with Andrews. Try:

    a process is any thread of execution or control which could be part of a program, running in different address spaces on the same processor as other processes (OS processes), e.g., a JVM is a process, or running on a different processor from other processes

    a (Java) Thread is a process running within a JVM.

    *You can think of Thread objects as where the JVM keeps information about a thread, e.g., its program counter, stack, registers values and so on.*There are basically three stages in the lifecycle of a Thread:

    creation: we make a new Thread by calling the constructor of a subclass of the Thread class or by passing an instance of a class which implements Runnable to the Thread constructoralive: calling the start() method on the Thread object invokes its run() method as an independent activity. After a Thread has been started, it is said to be alive. A thread which is alive is either runnable or not runnable. termination: the Thread terminates when its run method completes, either by returning normally or by throwing an unchecked exception (RuntimeException, Error or one of their subclasses). Threads are not restartable, even after they terminate---invoking start() more than once results in an InvalidThreadStateException.

    This slide summarises the states a Thread can be in and some of the more important transitions between the states. In the rest of the lecture I will say a little about each of these stages.

    *RUN THE ParticleApplet DEMO

    ParticleApplet creates n Particle objects, sets each particle in autonomous continuous motion, and periodically updates the display to show their current positions.

    there are several ways to implement thisamong the simplest is to associate an independent loop with each particle and to run each looping action in a different thread.

    the aim of the example is to reinforce the idea that there are multiple things happening at once, and that this involves multiple threads reading and writing the same data at about the same time.

    in this example there are at least 12 threads and possibly more, depending on how the browser handles applets.

    *There are three classes:

    Particle: which represents the position and behaviour of a particle, and which can draw the particle at its current position when asked to do so;

    ParticleCanvas: which provides a drawing area for the Particles, and which periodically asks the Particles to draw themselves at their current position; and

    ParticleApplet: which creates the Particles and the canvas and sets the particles in motion.

    To comply with Applet conventions, these activities should begin when Applet.start is invoked by a web browser, and should end when Applet.stop is called. We could also use buttons on the applet to start and stop the Particles.

    This example is based on one in the Lea Concurrent Programming in Java book, but I have modified it to illustrate different ways of creating threads.Lea uses a different approach in which the Particles are passive and are animated by threads created by the applet.*Having defined our Thread class and its behaviour, the next thing to do is to create some threads and run them.There are basically three stages in the lifecycle of a Thread:

    creation: we make a new Thread by calling the constructor of a subclass of the Thread class or by passing an instance of a class which implements Runnable to the Thread constructor

    *Threads in Java are represented by Thread objects.

    There are two ways to define a Thread class:

    extending the Thread class (which is part of java.lang) and overriding its run() method; or

    implementing the Runnable interface and its run() method.

    The Thread class implements Runnable. The default run() method provided by the Thread class simply returns immediately, so to get any useful work done by the thread you have to redefine the run() method in the subclass.

    If you choose the second option, the run() method has no implementation associated with it, so again you have to provide one.

    The second form is more common as it means the thread can extend another class. For example, if you want an applet to run in its own thread, you have to implement the Runnable interface as applets have to extend Applet. *The ParticleApplet contains examples of both approaches.

    The Particle class is an example of the first approach ---the Particle class extends Thread and overrides Threads run() method.

    Here the run() method simply calls the Particles move() method every 100 milliseconds to animate the particle.

    Well retun to the try {} catch {} later in the lecture.

    *The ParticleCanvas class is an example of the second approach.

    To get the ParticleCanvas to run in its own thread, we have to implement the Runnable interface, as we have to extend the AWT Canvas class to get the graphics functionality.

    Here the run() method simply repaints the Canvas every 100 milliseconds to display the current position of the Particles.

    The class constructor initialises the particles field to an empty array of Particles to simplify and enforce proper usage, the particles field is never allowed to be null. It could be argued that this is excessively defensive in the context, since the particles field is set before the ParticleCanvas thread is started, but, for correctness, if we didnt do this we would have to check that the return value of getParticles() is not null in paint() before trying to iterate over the ps array.

    *Now that we have our Runnable classes and defined their behaviour, the next thing to do is to make some Thread objects and run them.

    In our example, this is done in the ParticleApplet start() method:

    I have highlighted the point at which the Particle threads are created in green.

    Particle extends Thread, so we can just call the Particle constructor to create a new Thread, passing the initial position of the particle as arguments to the constructor (all particles start in the centre of the canvas).*The point at which the ParticleCanvas thread is created is highlighted in blue. Since ParticleCanvas implements the Runnable interface, we cant make the Thread directly: instead we pass a Runnable object to the Thread constructor.

    Once we have created the Threads, we give them names for debugging purposes and then call the Thread start() method. We cant call the run() method directly because the JVM has to create some internal datastructures to handle the new thread.

    Calling start() makes the thread runnable.

    Question: what would happen if we created and started the ParticleCanvas before the Particles?

    Answer: all particles would be drawn in the centre of the screen.

    *The second stage in the lifecycle of a Thread:

    alive: calling the start() method on the Thread object invokes its run() method as an independent activity.

    After a Thread has been started, it is said to be alive.

    A thread which is alive is either runnable or not runnable.

    *The applet makes 11 threads and starts them running. Lets look at what is actually happening when the applet is running

    for the Particle threads, the run() method simply calls the Particles move() method to animate the particle.

    it then sleeps for 100 milliseconds. sleep() is a static method of Thread which simply puts the thread to sleep.

    this is one way of allowing the other threads to run, if we only have a single processor. However its important to understand that the JVM may switch to running another thread at any point, e.g., in the middle of the move method, and not just at the point at which sleep() is called.

    if the JVM only did switch at sleep or yield points, we would have a style of concurrent programming called co-routineing rather than pre-emptive scheduling used by the JVM.*At some point, the JVM will switch to running the ParticleCanvas thread.

    Here the run() method simply repaints the Canvas to display the current position of the Particles.

    it them sleeps for 100 milliseconds.

    Question: why do we have to call Thread.sleep() here?

    Answer: we are not extending Thread.

    Question: would we get smoother animation if we reduced the sleep interval of the ParticleCanvas thread? For example, suppose we wanted 60 frames a second like a modern computer game and slept for only 15 milliseconds.

    Answer: no, because the Particle positions would still only be updated every tenth of a secondmostly we would just draw the Particles more frequently in the same positions.*The second stage in the lifecycle of a Thread:

    alive: calling the start() method on the Thread object invokes its run() method as an independent activity.

    After a Thread has been started, it is said to be alive.

    A thread which is alive is either runnable or not runnable.

    *A running Thread becomes not-runnable when:

    it blocks in wait()for condition synchronisation;

    it calls sleep() to tell the scheduler that it no longer wants to run

    it blocks for I/O

    Well come back to wait and I/O in future lectures.**A Thread becomes not runnable if it tells the JVM that it no longer wants to run.

    The Thread class provides the following static scheduling methods:

    sleep(long msecs): causes the current thread to suspend for at least msecs milliseconds.

    yield: requests that the JVM to run any other runnable but non-running thread rather than the current thread.

    Because they are static, they can only be applied to the thread that is currently running.

    yield can be effective on some single-CPU JVM implementations that dont use time-sliced pre-emptive scheduling. However, on JVM implementations that employ pre-emptive scheduling, especially those on multi-processors, it is possible and even desirable that the scheduler should ignore the hint given by yield.*Java makes no promises about scheduling or fairness, and does not even strictly guarantee that threads make forward progress. However Threads support priority methods which heuristically influence schedulers:

    each thread has a priority in the range Thread.MIN_PRIORITY to Thread.MAX_PRIORITY

    by default, each new thread has the same priority as the thread that created it---the initial thread associated with a main method by default has priority Thread.NORM_PRIORITY

    the current priority of a thread can be accessed by the method getPriority and set via the method setPriority.

    When there are more runnable threads than CPUs, a scheduler is generally biased in favour of threads with higher priorities. The exact policy may and does vary across platforms.

    In a multiprogramming implementation, all the threads comprising a Java program are scheduled by the OS as a single unit: the program gets a timeslice and it is up the the JVM to work out how to share this among the threads.*Finally, I want to look at how we stop the threads.

    The third stage in the lifecycle of a Thread is termination.

    *A Thread terminates when its run method completes, either by returning normally or by throwing an unchecked exception (RuntimeException, Error or one of their subclasses).

    Threads are not restartable, even after they terminate---invoking start() more than once results in an InvalidThreadStateException.

    Well focus on normal returns.*A program will continue to run until its last (non-daemon) thread terminates. It is not enough for the main thread to terminate---you must arrange to shut down any other threads you have created. This is sometimes called thread cancellation.

    There are several ways to get a thread to stop:

    the easiest way is for the threads run() method to return normally. However, if the thread is in an infinite loop the run() method will never return.

    another way to shut down a thread is to call Thread.stop(). However, this is a bad idea, as it doesnt allow the thread to clean up before it dies. In particular, the stopped thread can terminate execution in the middle of a synchronised block or method, leaving an object in an inconsistent state.

    A better approach is to interrupt the thread.

    *Each Thread has an associated boolean interruption status. Calling interrupt on a thread sets the threads interruption status to true. A thread can then periodically check its interrupted status, and if it is true, clean up and exit.

    interrupt(): sets the threads interrupted status to true unless the thread is blocked on Object.wait, Thread.sleep or Thread.join, when it causes these methods to throw InterruptedException and sets the threads interrupted status to false.

    isInterrupted(): returns true if the thread has been interrupted by Thread.interrupt and the status has not been reset by the thread invoking Thread.interrupted or by Object.wait, Thread.sleep or Thread.join throwing an InterruptedException.

    Thread.interrupted: clears the interruption status of the current Thread and returns the previous status. This is a static method, so one threads interrupted status cant be cleared from other threads.

    *Threads which are blocked in calls to the methods wait, and sleep arent runnable, and cant check the value of the interrupted flag.

    Interrupting a thread which is waiting, sleeping or joining aborts the thread and throws an InterruptedException.

    When an InterruptedException is thrown, we basically have two choices:

    catch the exception and handle it

    declare the exception in your throws clause and let the exception pass through your method (possibly with a finally clause to clean up first).

    Which is correct depends on what we want to do. However in the case of a run() method, we cant allow the exception to propagate, since we cant change the signature of the method.

    This is why calls to wait(), and sleep() are typically enclosed in try-catch blocks to handle InterruptedExceptions thrown when the thread is interrupted.

    [Removed references to join(), as it isnt mentioned on the diagram.]

    *Interrupting the Particle Threads

    This is the stop() method for the ParticleApplet class.It checks to see if we have any Particle threads, and if we do, interrupts each one. It then interrupts the ParticleCanvas thread. This doesnt actually stop the threads---it just informs them that we would like them to stop as soon as it is safe for them to do so.

    The start() and stop() methods are synchronized to prelcude concurrent starts or stops.

    Note that we dont use the Thread.stop() method to terminate the threads.*Returning from the run() method

    The run() method for Particles catches the InterruptedExceptions thrown while the thread is sleeping and simply returns, terminating the thread which animates the particle.

    The run() method for ParticleCanvas is similar---when it is interrupted, it simply stops repainting the particles.

    What happens if the thread is interrupted while, e.g., moving the particle? Should the run method also check its interrupted status regularly, or will the sleep throw an InterruptedException on entry if the interrupted status of the thread is true?**A variant of the second approach which is often seen is to use an anonymous class to implement the Runnable interface. For example, the original version of the ParticleApplet in the Lea book uses this approach.

    Here, the applet has a makeThread() method which creates an instance of an anonymous class which implements the Runnable interface. An instance of this class is passed to the Thread constructor to make a thread.

    This is sometimes done when wrapping existing sequential code in a thread to run multiple copies in parallel or to incorporate it into a multi-threaded program, or when the thread has no meaning in the program other than as an execution context.

    However, in a simple example like this, it doesnt really matter which you use. [Though Leas approach means that all the particles draw themselves whenever any of them movesthis may give smoother animation?]