Principles of Software Construction: Introduction to Multithreading - - PowerPoint PPT Presentation

principles of software construction
SMART_READER_LITE
LIVE PREVIEW

Principles of Software Construction: Introduction to Multithreading - - PowerPoint PPT Presentation

Principles of Software Construction: Introduction to Multithreading and GUI Programming Christian Kaestner and Bogdan Vasilescu School of Computer Science 15-214 1 Administrivia Homework 4a due tonight Please follow naming conventions


slide-1
SLIDE 1

1

15-214

School of Computer Science

Principles of Software Construction: Introduction to Multithreading and GUI Programming

Christian Kaestner and Bogdan Vasilescu

slide-2
SLIDE 2

2

15-214

Administrivia

  • Homework 4a due tonight

– Please follow naming conventions – Please mark last commit

  • Homework 4b due March 9
  • Reading for Tuesday: Adapter and Abstr. Factory
slide-3
SLIDE 3

3

15-214

slide-4
SLIDE 4

4

15-214

Key concept from yesterday's recitation

  • Discovering design patterns
  • The Observer pattern
slide-5
SLIDE 5

5

15-214

The Observer design pattern

slide-6
SLIDE 6

6

15-214

The Observer design pattern

  • Applicability

– When an abstraction has two interdependent aspects and you want to reuse both – When state change to one

  • bject requires notifying
  • thers, without becoming

dependent on them

  • Consequences

– Loose coupling between subject and observer, enhancing reuse – Support for broadcast communication – Notification can lead to further updates, causing a cascade effect

slide-7
SLIDE 7

7

15-214

EVENT-BASED PROGRAMMING

slide-8
SLIDE 8

8

15-214

Event-based programming

  • Style of programming where control-flow is

driven by (usually external) events

public void performAction(ActionEvent e) { List<String> lst = Arrays.asList(bar); foo.peek(42) } public void performAction(ActionEvent e) { bigBloatedPowerPointFunction(e); withANameSoLongIMadeItTwoMethods(e); yesIKnowJavaDoesntWorkLikeThat(e); } public void performAction(ActionEvent e) { List<String> lst = Arrays.asList(bar); foo.peek(40) }

slide-9
SLIDE 9

9

15-214

Examples of events in GUIs

  • User clicks a button, presses a key
  • User selects an item from a list, an item from a menu, expands a

tree

  • Mouse hovers over a widget, focus changes
  • Scrolling, mouse wheel turned
  • Resizing a window, hiding a window
  • Drag and drop
  • A package arrives from a web service, connection drops, …
  • System shutdown, …
slide-10
SLIDE 10

10

15-214

Interaction with command-line interfaces

Scanner input = new Scanner(System.in); while (questions.hasNext()) { Question q = question.next(); System.out.println(q.toString()); String answer = input.nextLine(); q.respond(answer); }

slide-11
SLIDE 11

11

15-214

GUIs without event-based programming

while (true) { if (isKeyDown(“Alt+Q”) break; if (isKeyDown(“F1”)

  • penHelp();

if (isMouseDown(10 …) startMovingWindow(); … }

slide-12
SLIDE 12

12

15-214

Event-based GUIs

//static public void main… JFrame window = … window.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE); window.setVisible(true); //on add-button click: String email = emailField.getText(); emaillist.add(email);

slide-13
SLIDE 13

13

15-214

Event-based GUIs

//static public void main… JFrame window = … window.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE); window.setVisible(true); //on add-button click: String email = emailField.getText(); emaillist.add(email); //on remove-button click: int pos = emaillist.getSelectedItem(); if (pos>=0) emaillist.delete(pos);

slide-14
SLIDE 14

14

15-214

(Blocking) Interactions with users

Game Player Dealer newGame addCards addCards getAction action [action==hit] addCard

blocking execution

slide-15
SLIDE 15

15

15-214

Interactions with users through events

  • Do not block waiting for user response
  • Instead, react to user events

– e.g.:

Game Player Dealer newGame addCards addCards hit addCard

slide-16
SLIDE 16

16

15-214

Typically use a GUI framework

  • Register code (a.k.a. callbacks,
  • bservers) to handle events
  • Operating system/GUI framework

detects events, determines which components are registered to handle the event and calls the event handlers

  • Program exits by calling some exit

method

GUI Framework OS Application

get event drawing commands next event event— mouse, key, redraw, …

slide-17
SLIDE 17

17

15-214

Programming an event-based GUI

  • Setup phase

– Describe how the GUI window should look – Use libraries for windows, widgets, and layout – Embed specialized code for later use – Register callbacks

  • Execution

– Framework gets raw events from OS (e.g., mouse clicks, key presses, window becomes visible) – Framework processes events (e.g., click at 10,40: which widget) – Triggers callback functions of corresponding widgets (if registered)

GUI Framework OS Application

get event drawing commands next event event— mouse, key, redraw, …

slide-18
SLIDE 18

18

15-214

Example: The AlarmWindow

  • …edu.cmu.cs.cs214.rec06.alarmclock.AlarmWin

dow

– Creates a JFrame with a JPanel to go in it – Creates a text label and a button – Makes the window (and its contents) visible when the alarm goes off

  • When the dismiss button is clicked, its event

handler hides the window

slide-19
SLIDE 19

19

15-214

Example: The CustomerManagementUI

  • …rec06.customerlist.gui.CustomerManagementUI

– Creates a JFrame with a JPanel to go in it – Makes the window (and its contents) visible

  • ...rec06.customerlist.gui.CustomerManagementPanel

– Creates numerous labels and text fields, a customerAddButton – Registers an event handler for the customerAddButton

  • When the customerAddButton is clicked, its event

handler gets the text from the text fields and adds a customer to the list

slide-20
SLIDE 20

20

15-214

MULTITHREADED PROGRAMMING BASICS

slide-21
SLIDE 21

21

15-214

What is a thread?

  • Short for thread of execution
  • Multiple threads run in same program concurrently
  • Threads share the same address space

– Changes made by one thread may be read by others

  • Multithreaded programming

– Also known as shared-memory multiprocessing

slide-22
SLIDE 22

22

15-214

Threads vs. processes

  • Threads are lightweight; processes heavyweight
  • Threads share address space; processes have own
  • Threads require synchronization; processes don’t

– Threads hold locks while mutating objects

  • It’s unsafe to kill threads; safe to kill processes
slide-23
SLIDE 23

23

15-214

Why use threads?

  • Performance in the face of blocking activities

– Consider a web server

  • Performance on multiprocessors
  • Cleanly dealing with natural concurrency
  • In Java threads are a fact of life

– Example: garbage collector runs in its own thread

slide-24
SLIDE 24

24

15-214

Example: generating cryptarithms

static List<String> cryptarithms(String[] words, int start, int end) { List<String> result = new ArrayList<>(); String[] tokens = new String[] {"", "+", "", "=", ""}; for (int i = start; i < end - 2; i++) { tokens[0] = words[i]; tokens[2] = words[i + 1]; tokens[4] = words[i + 2]; try { Cryptarithm c = new Cryptarithm(tokens); if (c.solve().size() == 1) result.add(c.toString()); } catch (IllegalArgumentException e) { // too many letters; ignore } } return result; }

slide-25
SLIDE 25

25

15-214

Single-threaded driver

public static void main(String[] args) { long startTime = System.nanoTime(); List<String> cryptarithms = cryptarithms(words, 0, words.length); long endTime = System.nanoTime(); System.out.printf("Time: %ds%n”, (endTime - startTime)/1e9); System.out.println(cryptarithms); }

slide-26
SLIDE 26

26

15-214

Multithreaded driver

public static void main(String[] args) throws InterruptedException { int n = Integer.parseInt(args[0]); // Number of threads long startTime = System.nanoTime(); int wordsPerThread = words.length / n; Thread[] threads = new Thread[n]; Object[] results = new Object[4]; for (int i = 0; i < n; i++) { // Create the threads int start = i == 0 ? 0 : i * wordsPerThread - 2; int end = i == n-1 ? words.length : (i + 1) * wordsPerThread; int j = i; // Only constants can be captured by lambdas threads[i] = new Thread(() -> { results[j] = cryptarithms(words, start, end); }); } for (Thread t : threads) t.start(); for (Thread t : threads) t.join(); long endTime = System.nanoTime(); System.out.printf("Time: %ds%n”, (endTime - startTime)/1e9); System.out.println(Arrays.toString(results)); }

slide-27
SLIDE 27

27

15-214

Cryptarithm generation performance

Number of Threads Seconds to run

1 22.0 2 13.5 3 11.7 4 10.8 Generating all cryptarithms from a corpus of 344 words

  • Test all consecutive 3-word sequences (342 possibilities)
  • Test machine is this crappy old laptop (2 cores, 4 hyperthreads)
  • I did not follow benchmarking best practices!
slide-28
SLIDE 28

28

15-214

What requires synchronization?

  • Shared mutable state
  • If not properly synchronized, all bets are off!
  • You have three choices
  • 1. Don’t mutate: share only immutable state
  • 2. Don’t share: isolate mutable state in individual threads
  • 3. If you must share mutable state, synchronize properly
slide-29
SLIDE 29

29

15-214

Synchronization is tricky

  • Too little and you risk safety failure

– Changes aren’t guaranteed to propagate thread to thread – Program can observe inconsistencies – Critical invariants can be corrupted

  • Too much and program may run slowly or not at all

– Deadlock or other liveness failure

slide-30
SLIDE 30

30

15-214

Contention kills performance

  • Synchronized is the opposite of concurrent!
  • Highly concurrent code is possible to write

– But it’s very difficult to get right – If you get it wrong you’re toast

  • Let Doug Lea write it for you!

– ConcurrentHashMap – Executor framework – See java.util.concurrent

slide-31
SLIDE 31

31

15-214

Safety vs. liveness

  • Safety failure – incorrect computation

– Can be subtle or blatant

  • Liveness failure – no computation at all
  • Temptation to favor liveness over safety

– Don’t succumb!

  • Safety failures offer a false sense of security
  • Liveness failures force you to confront the bug
slide-32
SLIDE 32

32

15-214

Synchronization in cryptarithm example

  • How did we avoid synchronization in our

multithreaded cryptarithm generator?

  • Embarrassingly parallelizable computation
  • Each thread is entirely independent of the others

– They try different cryptarithms – And write results to different array elements

  • No shared mutable state to speak of

– Main thread implicitly syncs with workers with join

slide-33
SLIDE 33

33

15-214

GUI PROGRAMMING

slide-34
SLIDE 34

34

15-214

There are many Java GUI frameworks

  • AWT – obsolete except as a part of Swing
  • Swing – the most widely used, by far
  • SWT – Little used outside of Eclipse
  • JavaFX – Billed as a replacement for Swing

– Released 2008 – has yet to gain traction

  • A bunch of modern (web & mobile) frameworks

– e.g., Android

slide-35
SLIDE 35

35

15-214

GUI programming is multithreaded

  • Event-driven programming
  • Event dispatch thread (EDT) handles all GUI events

– Mouse events, keyboard events, timer events, etc.

  • Program registers callbacks (“listeners”)

– Function objects invoked in response to events – Observer pattern

slide-36
SLIDE 36

36

15-214

Ground rules for GUI programming

  • 1. All GUI activity is on event dispatch thread
  • 2. No other time-consuming activity on this thread

– Blocking calls (e.g., I/O) absolutely forbidden

  • Many GUI programs violate these rules

– They are broken

  • Violating rule 1 can cause safety failures
  • Violating rule 2 can cause liveness failures
slide-37
SLIDE 37

37

15-214

Ensuring all GUI activity is on EDT

  • Never make a Swing call from any other thread
  • Swing calls includes Swing constructors
  • If not on EDT, make Swing calls with invokeLater:

public static void main(String[] args) { SwingUtilities.invokeLater(() -> new Test().setVisible(true)); }

slide-38
SLIDE 38

38

15-214

Callbacks execute on the EDT

  • You are a guest on the Event Dispatch Thread!
  • Don’t abuse the privilege
  • If you do, liveness will suffer

– Your program will become non-responsive – Your users will become angry

  • If > a few ms of work to do, do it off the EDT

– javax.swing.SwingWorker designed for this purpose

slide-39
SLIDE 39

39

15-214

Swing has many widgets

  • JLabel
  • JButton
  • JCheckBox
  • JChoice
  • JRadioButton
  • JTextField
  • JTextArea
  • JList
  • JScrollBar
  • … and more
  • JFrame is the Swing Window
  • JPanel (aka a pane) is the container to which you add your components (or
  • ther containers)
slide-40
SLIDE 40

40

15-214

To create a simple Swing application

  • Make a Window (a JFrame)
  • Make a container (a JPanel)

– Put it in the window

  • Add components (Buttons, Boxes, etc.) to the container

– Use layouts to control positioning – Set up observers (a.k.a. listeners) to respond to events – Optionally, write custom widgets with application-specific display logic

  • Set up the window to display the container
  • Then wait for events to arrive…
slide-41
SLIDE 41

41

15-214

Creating a button

//static public void main… JFrame window = … JPanel panel = new JPanel(); window.setContentPane(panel); JButton button = new JButton(“Click me”); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println(“Button clicked”); } }); panel.add(button); window.setVisible(true);

slide-42
SLIDE 42

42

15-214

Creating a button

//static public void main… JFrame window = … JPanel panel = new JPanel(); window.setContentPane(panel); JButton button = new JButton(“Click me”); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println(“Button clicked”); } }); panel.add(button); window.setVisible(true);

panel to hold the button

slide-43
SLIDE 43

43

15-214

Creating a button, Java 8

//static public void main… JFrame window = … JPanel panel = new JPanel(); window.setContentPane(panel); JButton button = new JButton(“Click me”); button.addActionListener((e) -> { System.out.println(“Button clicked”); } }); panel.add(button); window.setVisible(true);

slide-44
SLIDE 44

44

15-214

ActionListeners

  • Listeners are objects with callback functions
  • Listeners can be registered to handle events on

widgets

  • All registered widgets are called if event occurs

interface ActionListener { void actionPerformed(ActionEvent e); }

class ActionEvent { int when; String actionCommand; int modifiers; Object source(); int id; … }

slide-45
SLIDE 45

45

15-214

ActionListeners

  • Listeners are objects with callback functions
  • Listeners can be registered to handle events on widgets
  • All registered widgets are called if event occurs

interface ActionListener { void actionPerformed(ActionEvent e); }

class ActionEvent { int when; String actionCommand; int modifiers; Object source(); int id; … }

class AbstractButton extends JComponent { private List<ActionListener> listeners; public void addActionListener(ActionListener l) { listeners.add(l); } protected void fireActionPerformed(ActionEvent e) { for (ActionListener l: listeners) l.actionPerformed(e); } }

slide-46
SLIDE 46

46

15-214

ActionListeners

  • Listeners are objects with callback functions
  • Listeners can be registered to handle events on widgets
  • All registered widgets are called if event occurs

interface ActionListener { void actionPerformed(ActionEvent e); }

class ActionEvent { int when; String actionCommand; int modifiers; Object source(); int id; … }

class AbstractButton extends JComponent { private List<ActionListener> listeners; public void addActionListener(ActionListener l) { listeners.add(l); } protected void fireActionPerformed(ActionEvent e) { for (ActionListener l: listeners) l.actionPerformed(e); } }

What design pattern is this?

slide-47
SLIDE 47

47

15-214

Recall the observer design pattern

slide-48
SLIDE 48

48

15-214

Design discussion

  • Button implementation should be reusable but

customizable

– Different button label, different event-handling

  • Must decouple button's action from the button

itself

  • Listeners are separate independent objects

– A single button can have multiple listeners – Multiple buttons can share the same listener

slide-49
SLIDE 49

49

15-214

Swing has many event listener interfaces:

  • ActionListener
  • AdjustmentListener
  • FocusListener
  • ItemListener
  • KeyListener
  • MouseListener
  • TreeExpansionListener
  • TextListener
  • WindowListener
  • …and on and on…

interface ActionListener { void actionPerformed(ActionEvent e); }

class ActionEvent { int when; String actionCommand; int modifiers; Object source(); int id; …

slide-50
SLIDE 50

50

15-214

DECOUPLING THE GUI

slide-51
SLIDE 51

51

15-214

A GUI design challenge

  • Consider a blackjack game, implemented by a Game class:

– Player clicks “hit” and expects a new card – When should the GUI update the screen? Game GUI update getData hit()

slide-52
SLIDE 52

52

15-214

A GUI design challenge, extended

  • What if we want to show the points won?

Game GUI update PointsPanel getData update getData update hit

slide-53
SLIDE 53

53

15-214

Game updates GUI?

  • What if points change for reasons not started by the GUI?

(or computations take a long time and should not block)

Game GUI update PointsPanel getData update getData update hit

slide-54
SLIDE 54

54

15-214

Game updates GUI?

  • Let the Game tell the GUI that something happened

Game GUI update PointsPanel update(data) update(data) update hit

slide-55
SLIDE 55

55

15-214

Game updates GUI?

  • Let the Game tell the GUI that something happened

Game GUI update PointsPanel update(data) update(data) update hit

Problem: This couples the World to the GUI implementation.

slide-56
SLIDE 56

56

15-214

Core implementation vs. GUI

  • Core implementation: Application logic

– Computing some result, updating data

  • GUI

– Graphical representation of data – Source of user interactions

  • Design guideline: Avoid coupling the GUI with core

application

– Multiple UIs with single core implementation – Test core without UI – Design for change, design for reuse, design for division of labor; low coupling, high cohesion

slide-57
SLIDE 57

57

15-214

Decoupling with the Observer pattern

  • Let the Game tell all interested components about updates

Game GUI register update PointsPanel notify notify update register hit

slide-58
SLIDE 58

58

15-214

Separating application core and GUI, a summary

  • Reduce coupling: do not allow core to depend
  • n UI
  • Create and test the core without a GUI

– Use the Observer pattern to communicate information from the core (Model) to the GUI (View)

Core GUI Core Tests GUI Tests

slide-59
SLIDE 59

59

15-214

An architectural pattern: Model-View- Controller (MVC)

Manage inputs from user: mouse, keyboard, menu, etc. Manage display of information on the screen Manage data related to the application domain

slide-60
SLIDE 60

60

15-214

Model-View-Controller (MVC)

Passive model Active model

http://msdn.microsoft.com/en-us/library/ff649643.aspx

slide-61
SLIDE 61

61

15-214

For help writing Swing code

  • Sun wrote a good tutorial

– http://docs.oracle.com/javase/tutorial/uiswing/

  • The many components shown with examples

– http://docs.oracle.com/javase/tutorial/uiswing/components/componentlist.html

  • Listeners supported by each component

– http://docs.oracle.com/javase/tutorial/uiswing/events/eventsandcomponents.html

slide-62
SLIDE 62

62

15-214

Summary

  • Multithreaded programming is genuinely hard

– But it’s a fact of life in Java

  • Neither under- nor over-synchronize

– Immutable types are your best friend – java.util.concurrent is your next-best friend

  • GUI programming is limited form of multithreading

– Swing calls must be made on event dispatch thread – No other significant work should be done on EDT

  • GUIs are full of design patterns