Friday, February 28, 2014

Example of using Lock/ReentrantLock

java.util.concurrent.locks.Lock implementations provide more extensive locking operations than can be obtained using synchronized methods and statements.
java.util.concurrent.locks.ReentrantLock is a reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities.

This example have the same function of the More example of Synchronized Statements with separate objects for locking (the 2nd example), implement with Lock.


package com.example.androidthread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

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;
  Lock lock1;
  Lock lock2;

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

  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();
   }

   int tmpCounter;
   lock1.lock();
   try{
    tmpCounter = counter1;

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

    tmpCounter--;
    counter1 = tmpCounter;
   }finally{
    lock1.unlock();
   }
   
   return tmpCounter;
   
  }
  
  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();
   }
   
   int tmpCounter;
   lock2.lock();
   try{
    tmpCounter = counter2;

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

    tmpCounter--;
    counter2 = tmpCounter;
   }finally{
    lock2.unlock();
   }
   
   return counter2;
   
  }
 }

}

The layout XML, refer to the former exercise of More example of Synchronized Statements with separate objects for locking.


- More example about Thread

No comments: