Gots ta move dat data...... and not trash your threads...

28
Gots ta move dat data... ... and not trash your threads...

Transcript of Gots ta move dat data...... and not trash your threads...

Gots ta move dat data...

... and not trash your threads...

Administrivia

•No noose is good noose...

A peek at history•Last time:

•Finished up the WOTL exercise

•Multi-processing and security: race conditions

•Today:

•Stupid Eclipse tricks

•Communicating with the Swing thread

•Timer threads

Client-side communications•Issue:

•Data enters client through network listener thread

•GUI being processed on Swing/AWT event queue

•Need to transfer data between them

•Need to handle synchronization...

Classic MVC designNetworkListenerthread

Model(GridWorld2d

+ stuff)

GUI datastructures

(JLabel, etc.)data

(server update) set(x,y,data)notify(x,y)

get(x,y)

Classic MVC designNetworkListenerthread

Model(GridWorld2d

+ stuff)

GUI datastructures

(JLabel, etc.)data

(server update) set(x,y,data)notify(x,y)

get(x,y)

SWING/AWTevent proc

threadGUI

event(click, etc.)

Danger Will

Robinson!

Multiple access!

Data corruption!

Here beMonsters!

What you wantNetworkListenerthread

Model(GridWorld2d

+ stuff)

GUI datastructures

(JLabel, etc.)data

(server update)

set(x,y,data)

notify(x,y)

get(x,y)

SWING/AWTevent proc

thread

A miracleoccurs

GUIevent

(click, etc.)Deferre

d!

WTF?

How to get there...

•Need some way for listener thread to:

•Store the incoming data temporarily

•Notify the event thread: “Hey! There’s some new data! Come deal with it!”

•Requires:

•Synchronized access to temp data store

•Rapid turnaround in listener thread

How to get there...

•Clever, clever SWING designers thought of this...

•javax.swing.SwingUtilities.invokeLater()

•Takes a Runnable

•Event thread executes Runnable.run() “when it’s convenient”

•After rest of outstanding AWT events have cleared

How to get there...

•Clever, clever SWING designers thought of this...

•javax.swing.SwingUtilities.invokeLater()

•Immediately returns control to calling thread (network listener)

•Executes Runnable.run() once

•Does not create a new thread

Network listener codepublic void listenToNetwork(Socket s) {

while (!toStop) {Message data= // read from networksynchronizedBuffer.add(data);SwingUtilities.invokeLater(new _msgHandler());

}}

Network listener codepublic void listenToNetwork(Socket s) {

while (!toStop) {Message data= // read from networksynchronizedBuffer.add(data);SwingUtilities.invokeLater(new _msgHandler());

}}

private static class _msgHandlerimplements Runnable {

public void run() {Message m=synchronizedBuffer.remove();while (m!=null) {

m.execute(model);m=synchronizedBuffer.remove();

}} } }

Alternately...public void listenToNetwork(Socket s) {

while (!toStop) {Message data= // read from networkSwingUtilities.invokeLater(new _msgHandler(data));

}}

private static class _msgHandlerimplements Runnable {

public _msgHandler(Message m) { _data=m; }public void run() {

m.execute(model);}private final Message _data;

}}

A final note•The example chat client you have does not do this

•May be a bug...

•... Or the author may know something I don’t

•This is my best understanding from SWING docs

•Caveat emptor!

Timer threads

Single thread solutionpublic void doYourThing(long period) {assert period>0;while (!_toStop) {long last=System.currentTimeMillis();// do inner loop stufflong delta=System.currentTimeMillis()-last;try {Thread.sleep(period-delta);

}catch (InterruptedException ex) {// do something with this

}}

}

Analysis of single-thread

•Tricky to handle “roll-over”

•What if “inner loop stuff” takes more than one period?

Analysis of single-thread

•System.currentTimeMillis() has some overhead

•Requires a trap to kernel space

•Small beans if period is long

Analysis of single-thread

•Hard to align w/ other threads

•Multiple timers running simultaneously

•Interface to GUI

•etc...

Multi-thread approaches•In general, want a multi-thread model

•“timer thread”: only job is to keep time beat

•“worker threads”: respond to timer, do something at each beat

•Can have many worker threads for one timer

•Possibilities:

•java.util.Timer

•javax.swing.Timer

•roll your own...

Timers behind the scenes

•Need 2 things:

•Time base: way to delay for p time units

•Communication: way to make some other thread do something

Timers behind the scenes•Time base:

•Thread.sleep(p)

•Object.wait(p)

•Essentially: Go to sleep now; wake up in p ms

•Both subject to InterruptedException

•Have to run in try/catch block

Timers behind the scenes

•wait requires that you “own the object’s monitor”

•Technically, you wait on a specific object

•Have to synchronize w.r.t. that object before you can call wait()

•sleep() does this implicitly for you

Thread communication•Timer thread can now

while (!_toStop) {try {this.wait(period);

}catch (InterruptedException ex) {}

}

•But what does it do next? How does it tell other threads to do something?

Thread communication

•Opposite of wait() is notify()/notifyAll()

•Picks one/all threads that are waiting on an object

•Breaks them out of any wait() they’re in

•They go back into normal thread schedule

Thread communication

•Like wait(), call notify() on a specific object

•Again, have to “own monitor for object” before can call notify() on it

•Essentially the “observable/observer” design pattern for multi-threaded apps

Thread communicationpublic Object sharedObject=new Object();

// in “worker” threadwhile (!done) {synchronized (sharedObject) {try {sharedObject.wait(); // indefinite wait

}catch (InterruptedException ex) {// do something

}}// do main stuff of loop

}

Thread communication// in “timer” threadwhile (!_toStop) {synchronized (this) {try {this.wait(period);

}catch (InterruptedException ex) {// do something with exception

}}synchronized (sharedObject) {sharedObject.notifyAll();

}}