G51PGP Programming Paradigms Lecture 009 Concurrency, exceptions 1
Reminder subtype polymorphism public class TestAnimals public static void main(string[] args) Animal[] animals = new Animal[6]; animals[0] = new Bear(); animals[1] = new Mouse(); animals[2] = new Mouse(); animals[3] = new Fish(); animals[4] = new Mouse(); animals[5] = new Bear(); Array of interface or object references Create objects and store in the array Each must implement interface or extend class for ( int i = 0 ; i < animals.length ; i++ ) System.out.println( "" + animals[i].getname() + "... " + animals[i].getnoise() ); The functions exist in animal class or interface Subclasses/implementers must provide implementations 2
Reminder : Interfaces Interfaces are just groups of function declarations No implementations for functions We say that these functions are abstract A class may implement multiple interfaces public interface Animal String getname(); String getnoise(); Subclass / Derived class Sub/derived class extends implements Superclass/base class Interface Base/superclass 3
Reminder: an inner class public class UsesButton public static void main( String[] args) new UsesButton ().go(); JFrame frame;// Member variable JLabel label;// Member variable JButton button; // Member variable UsesButton ButtonPressHandler class ButtonPressHandler implements ActionListener // Inner class public void actionperformed( ActionEvent e) label.settext(label.gettext()+"."); frame.pack(); // accesses members of the surrounding class public void go() other code also exists in this function! button = new JButton("Press Me"); button.addactionlistener( new ButtonPressHandler()); See lecture 8, Example2. Each inner class object has a relationship to a specific outer class object. Note: Could also Include a one-way association arrow NOT inheritance (which is triangle arrow head) And could have used containment 4
Reminder: anonymous class public class UsesButton public static void main( String[] args) new UsesButton ().go(); UsesButton JFrame frame;// Member variable JLabel label;// Member variable JButton button; // Member variable public void go() other code also exists in this function! button = new JButton("Press Me"); button.addactionlistener( new ActionListener() ); // Anonymous inner class extends or implements ActionListener public void actionperformed( ActionEvent e) label.settext(label.gettext()+"."); frame.pack(); // accesses members of the surrounding class <<anonymous>> ActionListener Just move the code into the location where you use it. You can only use the class once because you have no way to refer to it. 5
Threads 6
Threads Threads are lightweight processes Your process can have multiple threads running inside it They share the same memory (process space) You can create your own threads There are some things that you need to be aware of Java provides simple fixes to avoid most problems You need to use the fixes though Swing creates its own worker thread when you display the first window You need to understand this Swing is not thread-safe only this worker thread should do any drawing not your own code!!! 7
Example of main thread doing things doother Stuff() creategui() Pick up event Handle event Main thread starts with main() When it creates the window (setvisible()) another thread will start Normally main() then ends Here we left main() running 8
Warning from last lecture You should not change the GUI from any thread other than the GUI thread The program I just used did so though This is very bad But we got away with it because nothing else was doing things Concept: thread safety A system is thread safe if multiple threads running at the same time and using it cannot cause problems Swing is NOT threadsafe!!! 9
InvokeLater interaction Worker Thread There is a simple way to move code to be called by the worker thread Ask worker thread to run the run() later when it can public void setlabeltext( String text ) // label.settext( text ); // label.invalidate(); // frame.pack(); EventQueue.invokeLater( new RunMe(text) ); class RunMe implements Runnable volatile String text; public RunMe( String text ) this.text = text; public void run() label.settext(text); label.invalidate(); frame.pack(); 10
Sharing data between threads Data which is shared between threads can cause problems: 1. Threads may keep their own copies for efficiency Other threads will not always see changes quickly Changes may overwrite changes from other threads 2. Optimiser may reorder the operations in a function if it looks like the order makes no difference but would be faster in another order If you only want to set something in one thread and read it in another, volatile may be the answer Tells runtime not to cache the variable locally Tells optimiser not to reorder accesses to volatile variables 11
Volatile member variables class RunMe implements Runnable volatile String text; public RunMe( String text ) this.text = text; public void run() label.settext(text); label.invalidate(); frame.pack(); Here the main thread will set the text (via constructor) The worker thread will use the text Note: No point in making a local variable volatile (so you can t) because it can only be seen by the thread running the function anyway 12
Creating your own threads Again the Runnable interface is used This is a common interface when you just want to ask something to run a function for you public interface Runnable public abstract void run(); class RunMe implements Runnable public void run() 13
Creating a thread Create an object which supports runnable Create a new Thread object and pass it the Runnable object Or create a new subclass of Thread Call start() on the thread object Do NOT call run() directly Start() will start a new thread and make it run the run() function class RunMe implements Runnable public void run() do something new Thread( new RunMe() ).start(); 14
My example : Threads2Race public class Threads2Race implements Runnable private static JFrame frame; private static JLabel label1; private static JLabel label2; private static JLabel label3; public static void main( String[] args) Create frame Use a grid layout Set a minimum size Create three labels Add labels to frame Add a winner label Tell frame to pack Set frame visible Start three threads: new Thread(new ThreadRace(label1)).start(); new Thread(new ThreadRace(label2)).start(); new Thread(new ThreadRace(label3)).start(); Track what is happening and update the winner label 15
The non-static parts private JLabel labelforthisitem; public Threads2Race( JLabel labeltouse ) labelforthisitem = labeltouse; public void run() for( int i = 0 ; i < 200 ; i++ ) for ( long j = 0 ; j < 200000000 ; j++ ) j = j; // Waste some time labelforthisitem.settext( labelforthisitem.gettext() + "." ); Warning: should have used invokelater, but I have simplified here 16
Class Diagram, more details Runnable ThreadRace + main() : void static + wait(): void static + ThreadRace() + run() : void -frame: JFrame -label1: JLabel -label2: JLabel -label3: JLabel - labelforthisitem: JLabel Static members are underlined + means public - means private # protected Implements interface is dashed line JFrame JLabel 17
Object Diagram Frame : JFrame : ThreadRace label1 : JLabel : ThreadRace label2 : JLabel : ThreadRace label3 : JLabel 18
Interference between threads // global counter - shared private static volatile long counter = 0; // This is executed from each of the threads public void run() labelforthisitem.settext( "Running..." ); for( long l = 0 ; l < 100000000 ; l++ ) counter++; labelforthisitem.settext( "Finished: " + counter ); Question: Three threads increment the counter 100,000,000 times. What should the total be? 19
Volatile is not the perfect answer: i++ Making changes appear immediately is not always good enough counter++ is not atomic Get counter value Increment value Store counter value Interleaving operations causes a problem A huge one in this case Because I used a tight loop to increase the chance 20
Simple fix: synchronized (US spelling) static class Monitor private long counter = 0; public synchronizedvoid inc() counter++; public synchronizedlong get() return counter; static Monitor mycounter; public static void main(string[] args) // Initialise the reference to monitor // prior to starting threads mycounter = new Monitor(); public void run() labelforthisitem.settext( "Running..." ); for( long l = 0 ; l < 100000000 ; l++ ) mycounter.inc(); labelforthisitem.settext( "Finished: " + mycounter.get() ); 21
Synchronized Two invocations of synchronized methods (the same or different) on the same object cannot interleave One completes before the other starts One will block (suspend execution) until the other finishes when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocationof a synchronized method for the same object (https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html) Therefore, changes to member variables (state) will be seen by other objects So hiding your data that is accessible between threads inside an object and only accessing through synchronized methods removes any problems A really nice, easy way to avoid issues (compared with C) Note: there may be more efficient ways of solving specific problems, but this way is guaranteed to work Problem with it is the blocking of other threads limit the time! 22
Exceptions 23
Exceptions Exceptions are like extra return values Returns an Exception object Or a subclass of an exception, since sub-class means IS-A When an exception is thrown, the function will end unless the exception is caught Then the caller function will end unless the exception is caught Etc functions will keep ending immediately until the exception is caught This couldbe a problem (IMO it IS a problem that you need to think carefully about in C++) so the designers of Java added some important features to help you If your function COULD raise an exception (i.e. you throw the exception or call function which can) then you must either: 1. Catch the exception in your function 2. Label the function so that it is clear that it raises an exception 24
The code for exceptions Throw an exception throw new InterruptedException("message text"); Catch exception (or subclass) catch clauses considered in order try foo1( i ); catch( InterruptedException e ) System.out.println( "Interrupted: " + e.getmessage() ); catch( Exception e ) System.out.println( "Exception: " + e.getmessage() ); Label the function if you don t catch the exceptions public static void foo1( int i ) throws InterruptedException 25
Exception test for ( int i = 0 ; i < 3 ; i++ ) Output: "Starting i = " + I try foo1( i ); catch(interruptedexception e) Output "Interrupted: " catch( Exception e ) Output "Exception: " Output "Ending i = " + i ); public static void foo1( int i ) throws InterruptedException Output: "Starting foo1()" if ( i == 1 ) throw new InterruptedException( "foo1() interrupted it!"); foo2( i ); Output: "Ending foo1()" public static void foo2( int i ) throws InterruptedException Output: "Starting foo2()" if ( i == 2 ) throw new InterruptedException( "foo2() interrupted it!"); Output: "Ending foo2()" 26
The wait function public static void wait( int milliseconds ) try Thread.sleep(milliseconds); catch(interruptedexception e) System.out.println(e); Thread.sleep() tells the current thread to sleep for a number of milliseconds But if something interrupts it, it will continue Instead of returning a value it throws an exception 27
Throwable In fact you can throw any Throwableobject, not just an exception Throwable has two sub-classes Exception Error Error indicates a serious problem that a reasonable application should not try to catch These indicate abnormal conditions that should never occur See for more information: https://docs.oracle.com/javase/8/docs/api/java/lang/er ror.html So throw Exception subclass objects 28
RuntimeException Subclass of exception Covers things that are not predictable or are common from many places and you don t want to have to always look for E.g. IndexOutOfBoundsException IllegalArgumentException You do not have to catch or declare a RuntimeException(or subclass) that you throw Avoid throwing a RuntimeExceptionsubclass object unless you don t want to force the caller to check for the exception 29
Throwing your own exceptions You can throw your own exceptions to indicate an error that you can t indicate through a return value Create or use a sub-class of Exception You can create a new subclass of a relevant exception and throw it Or you can throw an appropriate standard exception type and change the text appropriately Particularly important if you want to report an error from a constructor Constructor has no return value so no other option really We will see examples next week 30
Next Lecture Collection classes Generics Examples using exceptions, arrays and null 31