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