Thursday, February 27, 2014

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

1 comment: