MobAppDev (Fall 2014): Circular Motion, Sinusoid Curves, & Application Objects: Part 03: Access...
-
Upload
vladimir-kulyukin -
Category
Technology
-
view
63 -
download
0
description
Transcript of MobAppDev (Fall 2014): Circular Motion, Sinusoid Curves, & Application Objects: Part 03: Access...
MobAppDev
Circular Motion, Sinusoid Curves, &
Application Objects Part 03: Access Synchronization
Vladimir Kulyukin
www.vkedco.blogspot.com
Outline● Review
Threads Static & Non-Static Synchronization Joining threads
● Access Synchronization
Review
How Threads Run
● Each thread starts and runs to completion● A thread finishes when its run() method finishes● A thread can never be re-started (calling start() more than
once on the same Thread object throws IllegalThreadStateException)
● The order in which the Runnable threads get to run is JVM-specific
How Threads Sleep & Yield● When a Thread goes to sleep (Thread.sleep() is executed) and
wakes up, it does not start running – it becomes Runnable and may be selected to run by the JVM scheduler
● A yielding Thread (Thread.yield() is executed) yields to the Threads with the same priorities but there is no guarantee that another Thread will be chosen by the JVM scheduler – the same Thread (the one that just yielded) may be chosen to run again and again
How to Synchronize in Java● Every Java Instance Object and Java Class Object has a
built-in lock● Non-static methods should synchronize on Instance Objects
(this Object)● Static methods should synchronize on Class Objects● Since there is only one lock per Object, once a Thread picks
up the lock, no other thread can enter until the first Thread finishes
How to Synchronize: Blocks & Methods
// Here is an example of a synchronized block
class MySync {
public void myMethod() {
synchronized(this) {
// do some stuff here
}
}
}
// Here is an example of a synchronized method
class MySync {
public void synchronized myMethod() {
// do some stuff here
}
}
How Threads Sync● Threads calling non-static synchronized methods/blocks block each
other if they synchronize on the same Instance Objects● Threads calling static synchronized methods/blocks block each other
if they synchronize on the same Class Objects● Threads executing static and non-static methods/blocks NEVER
block each other● Rule of Thumb: Be careful when mixing static and non-static
synchronization and check which Thread synchronizes on which object
Joining Threads
● Thread.join() is the method that allows one thread to wait until another thread completes
● th.join(): the current thread waits until thread th completes
● th.join(int wait_time): wait_time specifies the waiting period (in milliseconds) for the current thread
Access Synchronization
When Should I Synchronize Access?
● Wherever there are concurrent threads that can access and modify the same objects or other resources, such as SQLite databases, questions of access synchronization must be addressed
● If access is not synchronized or synchronized incorrectly, objects and/or data may become inconsistent
Example
Write an application that starts four concurrent threads. Each thread randomly moves a small circle on the canvas. Threads can dance synchronously (one circle per time) or asynchronously (all circles move as they please)
source code is in DancingCirclesApp repo
Screenshots
Application Details: Synchronized Dance● The application creates four circle objects on a custom view's (PainterView.java)
canvas and uses four threads to randomly move four circles on the canvas● The main activity (DancingCirclesAct.java) defines an options menu with three
items: Synchronized Dance, Unsynchronized Dance, and Stop the Dance ● When the user presses Synchronized Dance, the activity starts four worker threads
with Runnables that synchronize on the PainterView object in DancingCirclesApp.java
● The configuration of the circles on the canvas of PainterView.java changes one circle at a time
● In a synchronized dance, one circle thread may usurp the CPU cycles for a while● Synchronization is implemented in the inner class SynchronizedPainterRunnable in
DancingCirclesAct.java
Application Details: Unsynchronized Dance● When the user selects Unsynchronized Dance, the activity starts four worker
threads with Runnables that do not synchronize on the PainterView object in DancingCirclesApp
● Therefore, the configuration of the circles on the canvas of the PainterView changes four circles at a time
● Asyncrhonization is implemented in the inner class UnsynchronizedPainterRunnable in DancingCirclesAct.java
● Note that both SychronizedPainterRunnable and UnsynchronizedPainterRunnable implement the Runnable interface
Access Synchronizationin
CircularMotion Application
source code is in this repo
Synchronizing Circular & Sinusoid Motions
● The sample synchronization principles are applied in the CircularMotion application
● The rotating circles objects are started in unsychronized threads
● The synchronization happens only when each circle is drawn on the canvas
Runnables that Moves Circlesclass UnsynchronizedPainterRunnable implements Runnable { Circle mCircle = null; boolean mThreadRunning = false; public UnsynchronizedPainterRunnable(Circle c) { mCircle = c; } @Override public void run() { mThreadRunning = true; while ( mThreadRunning ) { ((RotatingCircle) mCircle).move(); try { // Have the thread sleep Thread.sleep(CircularMotionMainActivity.SLEEP_INTERVAL); } catch (InterruptedException e) { e.printStackTrace(); mThreadRunning = false; } } }}
While the thread is running, the circle object stored in mCircle is cast into RotatingCircle (implemented in RotatingCircle.java)and moved (i.e., rotated a specific amount around the coordinate center on the left of the custom view). The thread then goes to sleep. This class is an inner class of CircularMotionMainActivity.java.
Starting Asynchronous Threadspublic class CircularMotionMainActivity extends Activity { ArrayList<Thread> mCircleThreads = null;
protected void onCreate(Bundle savedInstanceState) { mCircleThreads = new ArrayList<Thread>(); startUnsynchronizedThreads(); }
private void startUnsynchronizedThreads() { Thread th = null; for(Circle c: mPainterView.getCircles()) { th = new Thread(new UnsynchronizedPainterRunnable(c)); mCircleThreads.add(th); th.start(); }}
The main activity creates an ArrayList of Threads. The onCreate() method of the main activity starts the threads and adds them to the ArrayList of Threads.
Thread Synchronization at Drawing Timepublic void draw(Canvas canvas) { final int width = canvas.getWidth(); final int height = canvas.getHeight(); // 1. draw background rectangle that covers the entire canvas canvas.drawRect(0, 0, width, height, mBackgroundPaint); // 2. synchronize and draw synchronized (this) { this.drawXAxis(canvas); this.drawYAxis(canvas); this.drawSinusoidXAxis(canvas); this.drawSinusoidYAxis(canvas); this.drawCirclesOnCanvas(canvas); this.drawSinusoidCurves(canvas); // 3. force the canvas to redraw this.invalidate(); }}
The synchronization happens in CircularMotionPainterView.java when all circles and sinusoids are drawn.