Lesson 11 - Java Synchronization CIS470 – V. Matos
EXAMPLE 1. Synchronized-blocks – Producer:Consumer Problem
packagecsu.matos;
// Example1. Java concurrency - synchronized blocks
//------
publicclass Main {
publicstaticvoid main(String[] args) {
CookieJarcookieJar = newCookieJar();
Producer p1 = new Producer(cookieJar, 1);
Producer p2 = new Producer(cookieJar, 2);
Consumer c1 = new Consumer(cookieJar, 1);
p1.start();
p2.start();
c1.start();
}
}
// ------
classCookieJar {
public Integer contents = 0;
publicint get() {
synchronized (contents) {
intcontentsCopy = contents;
contents = 0;
returncontentsCopy;
}
}
publicint put(intvalue) {
synchronized (contents) {
contents += value;
returncontents;
}
}
}
// ------
class Consumer extends Thread {
privateCookieJarCookieJar;
privateintconsumerID;
public Consumer(CookieJarc, intconsumerID) {
CookieJar = c;
this.consumerID = consumerID;
}
publicvoid run() {
intvalue = 0;
for (inti = 0; i < 10; i++) {
value = CookieJar.get();
System.out.println("Consumer #" + this.consumerID + "\tgot: "+ value);
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedExceptione) {
}
}
}
}
// ------
class Producer extends Thread {
privateCookieJarcookieJar;
privateintproducerId;
public Producer(CookieJarc, intproducerId) {
cookieJar = c;
this.producerId = producerId;
}
publicvoid run() {
for (inti = 0; i < 10; i++) {
cookieJar.put(i);
System.out.println("Producer #" + this.producerId + "\tput: " + i
+ "\ttotalCookies=" + cookieJar.contents);
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedExceptione) {
}
}
}
}
Console
Producer #1put: 0totalCookies=0
Producer #2put: 0totalCookies=0
Consumer #1got: 0
Producer #1put: 1totalCookies=1
Producer #2put: 1totalCookies=2
Producer #2put: 2totalCookies=4
Producer #1put: 2totalCookies=6
Consumer #1got: 6
Consumer #1got: 0
Producer #1put: 3totalCookies=3
Consumer #1got: 3
Producer #1put: 4totalCookies=4
Producer #1put: 5totalCookies=9
Producer #2put: 3totalCookies=12
Producer #2put: 4totalCookies=16
Consumer #1got: 16
Consumer #1got: 0
Producer #1put: 6totalCookies=6
Producer #1put: 7totalCookies=13
Producer #2put: 5totalCookies=18
Producer #2put: 6totalCookies=24
Consumer #1got: 24
Producer #1put: 8totalCookies=8
Producer #2put: 7totalCookies=15
Consumer #1got: 15
Producer #2put: 8totalCookies=8
Producer #1put: 9totalCookies=17
Consumer #1got: 17
Producer #2put: 9totalCookies=9
Consumer #1got: 9
Example2. Consumer/Producer Problem - Java synchronization using Read-Write Locks
packagecsu.matos;
importjava.util.concurrent.locks.ReadWriteLock;
importjava.util.concurrent.locks.ReentrantReadWriteLock;
// Java concurrency - ReadWrite Locks
//------
publicclass Main {
publicstaticvoid main(String[] args) {
final Integer totalSimulationTime = 3000;
CookieJarcookieJar = newCookieJar();
SimulationClockclock = newSimulationClock(totalSimulationTime);
Producer p1 = new Producer(cookieJar, clock, 1);
Consumer c1 = new Consumer(cookieJar, clock, 1);
Consumer c2 = new Consumer(cookieJar, clock, 2);
clock.start();
p1.start();
c1.start();
c2.start();
}
}
// ------
classSimulationClockextends Thread {
Integer totalSimulationTime;
Integer currentClock = 0;
public SimulationClock( Integer totalSimulationTime) {
this.totalSimulationTime = totalSimulationTime;
}
@Override
publicvoid run() {
intsleepTime = 1000;
while (currentClocktotalSimulationTime) {
try {
Thread.sleep(sleepTime);
currentClock += sleepTime;
System.out.println("Tick-tack " + currentClock);
} catch (InterruptedExceptione) {
}
}
System.out.println("Time Over...... ");
}
}
// ------
classCookieJar {
privateintcontents;
ReadWriteLockrwLock = newReentrantReadWriteLock();
publicint get() {
rwLock.writeLock().lock();
intcontentsBackup = contents;
contents = 0;
rwLock.writeLock().unlock();
returncontentsBackup;
}
publicint put(intvalue) {
rwLock.writeLock().lock();
contents += value;
rwLock.writeLock().unlock();
returncontents;
}
}
// ------
class Consumer extends Thread {
privateCookieJarcookieJar;
privateintconsumerID;
privateSimulationClockclock;
finalintconsumerSleepTime = 1000;
public Consumer(CookieJarc, SimulationClockclock, intconsumerID ) {
cookieJar = c;
this.consumerID = consumerID;
this.clock = clock;
}
publicvoid run() {
intvalue = 0;
for (inti = 0; clock.currentClockclock.totalSimulationTime ; i++) {
value = cookieJar.get();
System.out.println("Consumer #" + this.consumerID + "\tgot: "+ value);
try {
sleep((int) (Math.random() * consumerSleepTime ));
} catch (InterruptedExceptione) {
}
}
}
}
// ------
class Producer extends Thread {
privateCookieJarcookieJar;
privateintproducerId;
privateSimulationClockclock;
privateintproducerSleepTime = 500;
public Producer(CookieJarc, SimulationClockclock, intproducerId) {
cookieJar = c;
this.producerId = producerId;
this.clock = clock;
}
publicvoid run() {
for (inti = 0; clock.currentClockclock.totalSimulationTime ; i++) {
inttotalCookies = cookieJar.put(i);
System.out.println("Producer #" + this.producerId + "\tput: " + i
+ "\ttotalCookies=" + totalCookies);
try {
sleep((int) (Math.random() * producerSleepTime));
} catch (InterruptedExceptione) {
}
}
}
}
Console
Consumer #1got: 0
Producer #1put: 0totalCookies=0
Consumer #2got: 0
Producer #1put: 1totalCookies=1
Producer #1put: 2totalCookies=3
Consumer #2got: 3
Consumer #1got: 0
Producer #1put: 3totalCookies=3
Producer #1put: 4totalCookies=7
Tick-tack 1000
Producer #1put: 5totalCookies=12
Producer #1put: 6totalCookies=18
Producer #1put: 7totalCookies=25
Producer #1put: 8totalCookies=33
Producer #1put: 9totalCookies=42
Consumer #2got: 42
Consumer #1got: 0
Producer #1put: 10totalCookies=10
Producer #1put: 11totalCookies=21
Producer #1put: 12totalCookies=33
Tick-tack 2000
Producer #1put: 13totalCookies=46
Consumer #2got: 46
Consumer #1got: 0
Consumer #1got: 0
Producer #1put: 14totalCookies=14
Producer #1put: 15totalCookies=29
Consumer #1got: 29
Tick-tack 3000
Time Over......
Example3: Producer/Consumer Problem – Using BlockingQueues
packagecsu.matos;
importjava.util.concurrent.ArrayBlockingQueue;
importjava.util.concurrent.BlockingQueue;
// Example3. Java concurrency - Producer/Consumer BlockingQueues
//------
publicclass Main {
publicstaticvoid main(String[] args) {
BlockingQueue<Integer> cookieJar = newArrayBlockingQueue<Integer>(4) ;
Producer p1 = new Producer(cookieJar, 1);
Producer p2 = new Producer(cookieJar, 2);
Consumer c1 = new Consumer(cookieJar, 1);
p1.start();
p2.start();
c1.start();
}
}
// ------
class Consumer extends Thread {
privateBlockingQueue<Integer> cookieJar;
privateintconsumerID;
public Consumer(BlockingQueue<Integer> c, intconsumerID) {
cookieJar = c;
this.consumerID = consumerID;
}
publicvoid run() {
intvalue = 0;
for (inti = 0; i < 10; i++) {
try {
value = cookieJar.take();
System.out.println("Consumer #" + this.consumerID + "\tgot: "
+ value);
sleep((int) (Math.random() * 100));
} catch (InterruptedExceptione) {
}
}
}
}
// ------
class Producer extends Thread {
privateBlockingQueue<Integer> cookieJar;
privateintproducerId;
public Producer(BlockingQueue<Integer> c, intproducerId) {
cookieJar = c;
this.producerId = producerId;
}
private String showQueue() {
Object[] a = cookieJar.toArray();
String result = cookieJar.size() + "[";
for (Object obj : a) {
result += obj + " ";
}
returnresult + "]";
}
publicvoid run() {
for (inti = 0; i < 10; i++) {
try {
//synchronized (this) {//otherwise you may print an ‘INCONSISTENT’ queue
cookieJar.put(i);
System.out.println("Producer #" + this.producerId
+ "\tput: " + i + "\n\t\tCookiesQueue="
+ showQueue());
//}
sleep((int) (Math.random() * 100));
} catch (InterruptedExceptione) {
}
}
}
}
Console
Producer #2put: 0
CookiesQueue=1[0 ]
Consumer #1got: 0
Producer #1put: 0
CookiesQueue=1[0 ]
Producer #1put: 1
CookiesQueue=2[0 1 ]
Producer #2put: 1
CookiesQueue=3[0 1 1 ]
Producer #2put: 2
CookiesQueue=4[0 1 1 2 ]
Consumer #1got: 0
Producer #1put: 2
CookiesQueue=4[1 1 2 2 ]
Consumer #1got: 1
Producer #2put: 3
CookiesQueue=4[1 2 2 3 ]
Consumer #1got: 1
Producer #2put: 4
CookiesQueue=4[2 2 3 4 ]
Consumer #1got: 2
Producer #1put: 3
CookiesQueue=4[2 3 4 3 ]
Producer #2put: 5
CookiesQueue=4[3 4 3 5 ]
Consumer #1got: 2
Consumer #1got: 3
Producer #1put: 4
CookiesQueue=4[4 3 5 4 ]
Consumer #1got: 4
Producer #2put: 6
CookiesQueue=4[3 5 4 6 ]
Consumer #1got: 3
Producer #1put: 5
CookiesQueue=4[5 4 6 5 ]
Consumer #1got: 5
Producer #2put: 7
CookiesQueue=4[4 6 5 7 ]
ANDROID – Producer/Consumer Message-Handler
package csu.matos;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class MainActivityextends Activity {
TextViewtxtMsg;
Handler handler= new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String strObj = (String)msg.obj;
txtMsg.append( "\n\n" + strObj );
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtMsg= (TextView) findViewById(R.id.txtMsg);
final Integer totalSimulationTime = 3000;
CookieJarcookieJar = new CookieJar();
SimulationClock clock = new SimulationClock(totalSimulationTime);
Producer p1 = new Producer(cookieJar, clock, 1);
Consumer c1 = new Consumer(cookieJar, clock, 1);
Consumer c2 = new Consumer(cookieJar, clock, 2);
clock.start();
p1.start();
c1.start();
c2.start();
}//onCreate
// ------
class SimulationClockextends Thread {
Integer totalSimulationTime;
Integer currentClock= 0;
public SimulationClock( Integer totalSimulationTime) {
this.totalSimulationTime= totalSimulationTime;
}
@Override
public void run() {
intsleepTime = 1000;
while (currentClocktotalSimulationTime) {
try {
Thread.sleep(sleepTime);
currentClock+= sleepTime;
String msg = "Tick-tack " + currentClock;
System.out.println(msg);
Message androMsg = handler.obtainMessage(1, msg);
handler.sendMessage(androMsg);
} catch (InterruptedException e) {
}
}
System.out.println("Time Over...... ");
}
}
// ------
class CookieJar {
private intcontents;
ReadWriteLockrwLock= new ReentrantReadWriteLock();
public intget() {
rwLock.writeLock().lock();
intcontentsBackup = contents;
contents = 0;
rwLock.writeLock().unlock();
return contentsBackup;
}
public intput(intvalue) {
rwLock.writeLock().lock();
contents += value;
rwLock.writeLock().unlock();
return contents;
}
}
// ------
class Consumer extends Thread {
private CookieJarcookieJar;
private intconsumerID;
private SimulationClockclock;
final intconsumerSleepTime= 1000;
public Consumer(CookieJar c, SimulationClock clock, intconsumerID ) {
cookieJar= c;
this.consumerID= consumerID;
this.clock= clock;
}
public void run() {
intvalue = 0;
for (inti = 0; clock.currentClockclock.totalSimulationTime; i++) {
value = cookieJar.get();
String msg = "Consumer #" + this.consumerID+ "\tgot: " + value;
System.out.println(msg);
Message androMsg = handler.obtainMessage(1, msg);
handler.sendMessage(androMsg);
try {
sleep((int) (Math.random() * consumerSleepTime));
} catch (InterruptedException e) {
}
}
}
}
// ------
class Producer extends Thread {
private CookieJarcookieJar;
private intproducerId;
private SimulationClockclock;
private intproducerSleepTime= 500;
public Producer(CookieJar c, SimulationClock clock, intproducerId) {
cookieJar= c;
this.producerId= producerId;
this.clock= clock;
}
public void run() {
for (inti = 0; clock.currentClockclock.totalSimulationTime; i++) {
inttotalCookies = cookieJar.put(i);
String msg = "Producer #" + this.producerId+ "\tput: " + i
+ "\ttotalCookies=" + totalCookies;
System.out.println(msg);
Message androMsg = handler.obtainMessage(1, msg);
handler.sendMessage(androMsg);
try {
sleep((int) (Math.random() * producerSleepTime));
} catch (InterruptedException e) {
}
}
}
}
}//Activity
Layout
LinearLayoutxmlns:android="
xmlns:tools="
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/scrollView"
<TextView
android:id="@+id/txtMsg"
android:text="@string/hello_world"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView
</LinearLayout