‏إظهار الرسائل ذات التسميات synchronized. إظهار كافة الرسائل
‏إظهار الرسائل ذات التسميات synchronized. إظهار كافة الرسائل

الاثنين، 3 مارس 2014

Solve Producer–consumer problem with wait() and notifyAll()

It's a example to solve the Producer–consumer problem with wait() and notifyAll().

In computing, the producer–consumer problem (also known as the bounded-buffer problem) is a classic example of a multi-process synchronization problem. The problem describes two processes, the producer and the consumer, who share a common, fixed-size buffer used as a queue. The producer's job is to generate a piece of data, put it into the buffer and start again. At the same time, the consumer is consuming the data (i.e., removing it from the buffer) one piece at a time. The problem is to make sure that the producer won't try to add data into the buffer if it's full and that the consumer won't try to remove data from an empty buffer. ~ http://en.wikipedia.org/wiki/Producer-consumer

Solve Producer–consumer problem
Solve Producer–consumer problem

package com.example.androidthread;

import java.util.LinkedList;
import java.util.Random;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

Button buttonStart;
TextView textInfoProducer, textInfoConsumer;

String infoMsgProducer;
String infoMsgConsumer;

ShareClass shareObj = new ShareClass();
long startingTime;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonStart = (Button) findViewById(R.id.buttonstart);
textInfoProducer = (TextView) findViewById(R.id.infoproducer);
textInfoConsumer = (TextView) findViewById(R.id.infoconsumer);

buttonStart.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {

infoMsgProducer = "Producer\n";
infoMsgConsumer = "Consumer\n";

Thread threadProducer = new Thread(new Runnable() {

@Override
public void run() {

int ele = 0;
Random random = new Random();

while (true) {
String strEle = String.valueOf(ele);
infoMsgProducer += strEle + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoProducer.setText(infoMsgProducer);
}
});

shareObj.produce(String.valueOf(ele));
long randomDelay = 500 + random.nextInt(1000);

try {
Thread.sleep(randomDelay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ele++;
}
}
});

Thread threadConsumer = new Thread(new Runnable() {

@Override
public void run() {

while (true) {
Random random = new Random();

while (true) {
infoMsgConsumer += shareObj.consume() + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoConsumer.setText(infoMsgConsumer);
}});

long randomDelay = 500 + random.nextInt(1000);

try {
Thread.sleep(randomDelay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
});

startingTime = System.currentTimeMillis();
threadProducer.start();
threadConsumer.start();
}
});

}

public class ShareClass {

final int BUFFER_MAX = 5;
LinkedList<String> buffer;

ShareClass(){
buffer = new LinkedList<String>();
}

public synchronized void produce(String element){

while(buffer.size() == BUFFER_MAX){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
buffer.offer(element);

notifyAll();
}

public synchronized String consume(){

while(buffer.size() == 0){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

String element = buffer.poll();
notifyAll();
return element;
}
}

}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/buttonstart"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="start()" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >

<TextView
android:id="@+id/infoproducer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />

<TextView
android:id="@+id/infoconsumer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />

</LinearLayout>

</LinearLayout>




- More example about Thread

الخميس، 27 فبراير 2014

More example of Synchronized Statements with separate objects for locking

Last example compare between Synchronization with single lock object and separate lock objects, one-on-one; one thread access one object and another object access another object. This example demonstrate a more complicated case, two threads access one object, and other two thread access another object.

Synchronized Statements with single object, this.
package com.example.androidthread;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

Button buttonStart;
TextView textInfoA, textInfoB, textInfoC, textInfoD;
TextView textDuration1, textDuration2;
TextView textDuration3, textDuration4;

String infoMsgA;
String infoMsgB;
String infoMsgC;
String infoMsgD;

ShareClass shareObj = new ShareClass(10);
long startingTime;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonStart = (Button) findViewById(R.id.buttonstart);
textInfoA = (TextView) findViewById(R.id.infoa);
textInfoB = (TextView) findViewById(R.id.infob);
textInfoC = (TextView) findViewById(R.id.infoc);
textInfoD = (TextView) findViewById(R.id.infod);
textDuration1 = (TextView) findViewById(R.id.duration1);
textDuration2 = (TextView) findViewById(R.id.duration2);
textDuration3 = (TextView) findViewById(R.id.duration3);
textDuration4 = (TextView) findViewById(R.id.duration4);

buttonStart.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {

infoMsgA = "Thread A\n";
infoMsgB = "Thread B\n";
infoMsgC = "Thread C\n";
infoMsgD = "Thread D\n";
textInfoA.setText(infoMsgA);
textInfoB.setText(infoMsgB);
textInfoC.setText(infoMsgC);
textInfoD.setText(infoMsgD);

Thread thread1 = new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter1() > 0) {

//caution:
//shareObj.counter1 may change here

infoMsgA += "A 1: "
+ shareObj.delayDecCounter1(500) + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoA.setText(infoMsgA);
}

});

} else {
stop = true;
final long endTime1 = System.currentTimeMillis();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textDuration1.setText("Duration 1 (reference only): "
+ (endTime1 - startingTime));
}

});
}
}
}
});

Thread thread2 = new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter2() > 0) {

//caution:
//shareObj.counter2 may change here

infoMsgB += "B 2: "
+ shareObj.delayDecCounter2(500) + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoB.setText(infoMsgB);
}

});

} else {
stop = true;
final long endTime2 = System.currentTimeMillis();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textDuration2.setText("Duration 2 (reference only): "
+ (endTime2 - startingTime));
}

});
}
}
}
});

//
Thread thread3 = new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter1() > 0) {

//caution:
//shareObj.counter1 may change here

infoMsgC += "C 1: "
+ shareObj.delayDecCounter1(200) + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoC.setText(infoMsgC);
}

});

} else {
stop = true;
final long endTime3 = System.currentTimeMillis();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textDuration3.setText("Duration 3 (reference only): "
+ (endTime3 - startingTime));
}

});
}
}
}
});

Thread thread4 = new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter2() > 0) {

//caution:
//shareObj.counter2 may change here

infoMsgD += "D 2: "
+ shareObj.delayDecCounter2(1100) + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoD.setText(infoMsgD);
}

});

} else {
stop = true;
final long endTime4 = System.currentTimeMillis();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textDuration4.setText("Duration 4 (reference only): "
+ (endTime4 - startingTime));
}

});
}
}
}
});
//

startingTime = System.currentTimeMillis();
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
});

}

public class ShareClass {

int counter1;
int counter2;

Object lock1;
Object lock2;

ShareClass(int c) {
counter1 = c;
counter2 = c;
lock1 = new Object();
lock2 = new Object();
}

public int getCounter1() {
return counter1;
}

public int getCounter2() {
return counter2;
}

public int delayDecCounter1(int delay) {

//do something not access the share obj
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

synchronized (this) {
int tmpCounter = counter1;

try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

tmpCounter--;
counter1 = tmpCounter;

return counter1;
}

}

public int delayDecCounter2(int delay) {

//do something not access the share obj
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

synchronized (this) {
int tmpCounter = counter2;

try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

tmpCounter--;
counter2 = tmpCounter;

return counter2;
}

}
}

}



Synchronized Statements with separate objects, lock1 and lock2.
package com.example.androidthread;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

Button buttonStart;
TextView textInfoA, textInfoB, textInfoC, textInfoD;
TextView textDuration1, textDuration2;
TextView textDuration3, textDuration4;

String infoMsgA;
String infoMsgB;
String infoMsgC;
String infoMsgD;

ShareClass shareObj = new ShareClass(10);
long startingTime;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonStart = (Button) findViewById(R.id.buttonstart);
textInfoA = (TextView) findViewById(R.id.infoa);
textInfoB = (TextView) findViewById(R.id.infob);
textInfoC = (TextView) findViewById(R.id.infoc);
textInfoD = (TextView) findViewById(R.id.infod);
textDuration1 = (TextView) findViewById(R.id.duration1);
textDuration2 = (TextView) findViewById(R.id.duration2);
textDuration3 = (TextView) findViewById(R.id.duration3);
textDuration4 = (TextView) findViewById(R.id.duration4);

buttonStart.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {

infoMsgA = "Thread A\n";
infoMsgB = "Thread B\n";
infoMsgC = "Thread C\n";
infoMsgD = "Thread D\n";
textInfoA.setText(infoMsgA);
textInfoB.setText(infoMsgB);
textInfoC.setText(infoMsgC);
textInfoD.setText(infoMsgD);

Thread thread1 = new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter1() > 0) {

//caution:
//shareObj.counter1 may change here

infoMsgA += "A 1: "
+ shareObj.delayDecCounter1(500) + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoA.setText(infoMsgA);
}

});

} else {
stop = true;
final long endTime1 = System.currentTimeMillis();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textDuration1.setText("Duration 1 (reference only): "
+ (endTime1 - startingTime));
}

});
}
}
}
});

Thread thread2 = new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter2() > 0) {

//caution:
//shareObj.counter2 may change here

infoMsgB += "B 2: "
+ shareObj.delayDecCounter2(500) + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoB.setText(infoMsgB);
}

});

} else {
stop = true;
final long endTime2 = System.currentTimeMillis();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textDuration2.setText("Duration 2 (reference only): "
+ (endTime2 - startingTime));
}

});
}
}
}
});

//
Thread thread3 = new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter1() > 0) {

//caution:
//shareObj.counter1 may change here

infoMsgC += "C 1: "
+ shareObj.delayDecCounter1(200) + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoC.setText(infoMsgC);
}

});

} else {
stop = true;
final long endTime3 = System.currentTimeMillis();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textDuration3.setText("Duration 3 (reference only): "
+ (endTime3 - startingTime));
}

});
}
}
}
});

Thread thread4 = new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter2() > 0) {

//caution:
//shareObj.counter2 may change here

infoMsgD += "D 2: "
+ shareObj.delayDecCounter2(1100) + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoD.setText(infoMsgD);
}

});

} else {
stop = true;
final long endTime4 = System.currentTimeMillis();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textDuration4.setText("Duration 4 (reference only): "
+ (endTime4 - startingTime));
}

});
}
}
}
});
//

startingTime = System.currentTimeMillis();
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
});

}

public class ShareClass {

int counter1;
int counter2;

Object lock1;
Object lock2;

ShareClass(int c) {
counter1 = c;
counter2 = c;
lock1 = new Object();
lock2 = new Object();
}

public int getCounter1() {
return counter1;
}

public int getCounter2() {
return counter2;
}

public int delayDecCounter1(int delay) {

//do something not access the share obj
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

synchronized (lock1) {
int tmpCounter = counter1;

try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

tmpCounter--;
counter1 = tmpCounter;

return counter1;
}

}

public int delayDecCounter2(int delay) {

//do something not access the share obj
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

synchronized (lock2) {
int tmpCounter = counter2;

try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

tmpCounter--;
counter2 = tmpCounter;

return counter2;
}

}
}

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/buttonstart"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="start()" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<TextView
android:id="@+id/infoa"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />

<TextView
android:id="@+id/infob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />

<TextView
android:id="@+id/infoc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />

<TextView
android:id="@+id/infod"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>

<TextView
android:id="@+id/duration1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/duration2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/duration3"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/duration4"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</LinearLayout>




- More example about Thread

Synchronized Statements with separate objects for locking

This example compare how Synchronized Statements with single object vs separate objects.

Synchronized Statements with single object, this.
package com.example.androidthread;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

Button buttonStart;
TextView textInfoA, textInfoB;
TextView textDuration1, textDuration2;

String infoMsgA;
String infoMsgB;

ShareClass shareObj = new ShareClass(10);
long startingTime;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonStart = (Button) findViewById(R.id.buttonstart);
textInfoA = (TextView) findViewById(R.id.infoa);
textInfoB = (TextView) findViewById(R.id.infob);
textDuration1 = (TextView) findViewById(R.id.duration1);
textDuration2 = (TextView) findViewById(R.id.duration2);

buttonStart.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {

infoMsgA = "Thread A\n";
infoMsgB = "Thread B\n";
textInfoA.setText(infoMsgA);
textInfoB.setText(infoMsgB);

Thread thread1 = new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter1() > 0) {

infoMsgA += "A 1: "
+ shareObj.delayDecCounter1(500) + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoA.setText(infoMsgA);
}

});

} else {
stop = true;
final long endTime1 = System.currentTimeMillis();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textDuration1.setText("Duration 1 (reference only): "
+ (endTime1 - startingTime));
}

});
}
}
}
});

Thread thread2 = new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter2() > 0) {

infoMsgB += "B 2: "
+ shareObj.delayDecCounter2(500) + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoB.setText(infoMsgB);
}

});

} else {
stop = true;
final long endTime2 = System.currentTimeMillis();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textDuration2.setText("Duration 2 (reference only): "
+ (endTime2 - startingTime));
}

});
}
}
}
});

startingTime = System.currentTimeMillis();
thread1.start();
thread2.start();
}
});

}

public class ShareClass {

int counter1;
int counter2;

ShareClass(int c) {
counter1 = c;
counter2 = c;
}

public int getCounter1() {
return counter1;
}

public int getCounter2() {
return counter2;
}

public int delayDecCounter1(int delay) {

//do something not access the share obj
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

synchronized (this) {
int tmpCounter = counter1;

try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

tmpCounter--;
counter1 = tmpCounter;

return counter1;
}

}

public int delayDecCounter2(int delay) {

//do something not access the share obj
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

synchronized (this) {
int tmpCounter = counter2;

try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

tmpCounter--;
counter2 = tmpCounter;

return counter2;
}

}
}

}



Synchronized Statements with separate objects, lock1 and lock2.
package com.example.androidthread;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

Button buttonStart;
TextView textInfoA, textInfoB;
TextView textDuration1, textDuration2;

String infoMsgA;
String infoMsgB;

ShareClass shareObj = new ShareClass(10);
long startingTime;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonStart = (Button) findViewById(R.id.buttonstart);
textInfoA = (TextView) findViewById(R.id.infoa);
textInfoB = (TextView) findViewById(R.id.infob);
textDuration1 = (TextView) findViewById(R.id.duration1);
textDuration2 = (TextView) findViewById(R.id.duration2);

buttonStart.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {

infoMsgA = "Thread A\n";
infoMsgB = "Thread B\n";
textInfoA.setText(infoMsgA);
textInfoB.setText(infoMsgB);

Thread thread1 = new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter1() > 0) {

infoMsgA += "A 1: "
+ shareObj.delayDecCounter1(500) + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoA.setText(infoMsgA);
}

});

} else {
stop = true;
final long endTime1 = System.currentTimeMillis();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textDuration1.setText("Duration 1 (reference only): "
+ (endTime1 - startingTime));
}

});
}
}
}
});

Thread thread2 = new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter2() > 0) {

infoMsgB += "B 2: "
+ shareObj.delayDecCounter2(500) + "\n";

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoB.setText(infoMsgB);
}

});

} else {
stop = true;
final long endTime2 = System.currentTimeMillis();
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textDuration2.setText("Duration 2 (reference only): "
+ (endTime2 - startingTime));
}

});
}
}
}
});

startingTime = System.currentTimeMillis();
thread1.start();
thread2.start();
}
});

}

public class ShareClass {

int counter1;
int counter2;

Object lock1;
Object lock2;

ShareClass(int c) {
counter1 = c;
counter2 = c;
lock1 = new Object();
lock2 = new Object();
}

public int getCounter1() {
return counter1;
}

public int getCounter2() {
return counter2;
}

public int delayDecCounter1(int delay) {

//do something not access the share obj
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

synchronized (lock1) {
int tmpCounter = counter1;

try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

tmpCounter--;
counter1 = tmpCounter;

return counter1;
}

}

public int delayDecCounter2(int delay) {

//do something not access the share obj
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

synchronized (lock2) {
int tmpCounter = counter2;

try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

tmpCounter--;
counter2 = tmpCounter;

return counter2;
}

}
}

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/buttonstart"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="start()" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<TextView
android:id="@+id/infoa"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />

<TextView
android:id="@+id/infob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>

<TextView
android:id="@+id/duration1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/duration2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</LinearLayout>

This example compare between Synchronization with single lock object and separate lock objects, one-on-one; one thread access one object and another object access another object. Next example demonstrate a more complicated case, two threads access one object, and other two thread access another object.


- More example about Thread

الأربعاء، 26 فبراير 2014

Share object between threads with Synchronized Statements

Last post show how to create synchronized code with Synchronized Method. Alternatively, we can synchronize block of code with Synchronized Statements.


Example code:
package com.example.androidthread;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

Button buttonStart;
TextView textInfoA, textInfoB;

String infoMsgA;
String infoMsgB;

ShareClass shareObj = new ShareClass(10);

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonStart = (Button) findViewById(R.id.buttonstart);
textInfoA = (TextView) findViewById(R.id.infoa);
textInfoB = (TextView) findViewById(R.id.infob);

buttonStart.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {

infoMsgA = "Thread A\n";
infoMsgB = "Thread B\n";
textInfoA.setText(infoMsgA);
textInfoB.setText(infoMsgB);

new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter() > 0) {

infoMsgA += "A: "
+ shareObj.delayDecCounter(2500) + "\n";

try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoA.setText(infoMsgA);
}

});

} else {
stop = true;
}
}
}
}).start();

new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter() > 0) {

infoMsgB += "B: "
+ shareObj.delayDecCounter(500) + "\n";

try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoB.setText(infoMsgB);
}

});

} else {
stop = true;
}
}
}
}).start();

}
});

}

public class ShareClass {

int counter;

ShareClass(int c) {
counter = c;
}

public int getCounter() {
return counter;
}

public int delayDecCounter(int delay) {

//do something not access the share obj
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

synchronized (this) {
int tmpCounter = counter;

try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

tmpCounter--;
counter = tmpCounter;

return counter;
}

}
}

}


The layout XML, refer to last post.


- More example about Thread

Share object between threads with synchronized methods

This example show how to synchronize share object between threads with synchronized methods.

Share object between threads WITH synchronized method


Share object between threads WITHOUT synchronized method


package com.example.androidthread;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

Button buttonStart;
TextView textInfoA, textInfoB;

String infoMsgA;
String infoMsgB;

ShareClass shareObj = new ShareClass(10);

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonStart = (Button) findViewById(R.id.buttonstart);
textInfoA = (TextView) findViewById(R.id.infoa);
textInfoB = (TextView) findViewById(R.id.infob);

buttonStart.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {

infoMsgA = "Thread A\n";
infoMsgB = "Thread B\n";
textInfoA.setText(infoMsgA);
textInfoB.setText(infoMsgB);

new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter() > 0) {

infoMsgA += "A: "
+ shareObj.delayDecCounter(2500) + "\n";

try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoA.setText(infoMsgA);
}

});

} else {
stop = true;
}
}
}
}).start();

new Thread(new Runnable() {

boolean stop = false;

@Override
public void run() {

while (!stop) {
if (shareObj.getCounter() > 0) {

infoMsgB += "B: "
+ shareObj.delayDecCounter(500) + "\n";

try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
textInfoB.setText(infoMsgB);
}

});

} else {
stop = true;
}
}
}
}).start();

}
});

}

public class ShareClass {

int counter;

ShareClass(int c) {
counter = c;
}

public int getCounter() {
return counter;
}

public synchronized int delayDecCounter(int delay) {

int tmpCounter = counter;

try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

tmpCounter--;
counter = tmpCounter;
return counter;
}
}

}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/buttonstart"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="start()" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="with synchronized" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >

<TextView
android:id="@+id/infoa"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />

<TextView
android:id="@+id/infob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>

</LinearLayout>

Next: Share object between threads with Synchronized Statements


- More example about Thread