Gots ta move dat data...... and not trash your threads...
-
Upload
rebecca-phillips -
Category
Documents
-
view
214 -
download
0
Transcript of Gots ta move dat data...... and not trash your threads...
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!
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
}