Tech I Enjoy Logo

Custom Search




  Home >> Java


A scenario to work on multi-threading and a typical design : This example is no way suggesting any best practice as such in any context. Someone asked me, whether there is a simple way of protecting data from corruption when data is not used in thread safe manner, like for example suppose there is a class A with a method to print incremental values, but this class A should be extended to a third party class SamplePlotter (this class is not coded as thread safe per se), as this class SamplePlotter is having an instance variable. This instance variable is suppose to hold the count number/value and increment it gradually. A.java
class A extends SamplePlotter
{
    public void print(int a) {
        System.out.println(""+setJ(a));
    }
}
SamplePlotter.java
class SamplePlotter 
{
  int j;
  public int setJ(int aj) {
	  j = j + aj;
	  return j;
  }
}
client.java
public class  client
{
  public client() {
    A a = new A();
    Worker w = new Worker(a);
    Thread th = new Thread(w, "TH1");
    //Thread th1 = new Thread(w, "TH2");
    th.start();
    //th1.start();
  }
  public static void main(String[] args) 
  {
     new client();
  }
}
class Worker implements Runnable
{
  private A a;
  boolean st = false;
  public Worker(A a) {
    this.a = a;
  }
  public void run() {
    for(int i=0;i<10;i++) {
      if(Thread.currentThread().holdsLock(a)) {
       a.notify();
      }
    System.out.println(Thread.currentThread().toString()+"   ");
    a.print(i);
    try
    {
      if(Thread.currentThread().holdsLock(a)) {
       Thread.currentThread().yield();
      }
    } catch (Exception ex){
      ex.printStackTrace();
    }
    }
  }
};
This class A <> SamplePlotter object hierarchy works well in a single thread, and the output is okay/as expected, shown as follows (by using the above client test program):
Thread[TH1,5,main]
0
Thread[TH1,5,main]
1
Thread[TH1,5,main]
3
Thread[TH1,5,main]
6
Thread[TH1,5,main]
10
Thread[TH1,5,main]
15
Thread[TH1,5,main]
21
Thread[TH1,5,main]
28
Thread[TH1,5,main]
36
Thread[TH1,5,main]
45
But if I am going to remove those commented lines in the public client constructor, thus adding another thread TH2 in this program, then the output is completely unacceptable/not expected, as shown below:
Thread[TH1,5,main]
0
Thread[TH1,5,main]
1
Thread[TH1,5,main]
3
Thread[TH1,5,main]
6
Thread[TH2,5,main]
6
Thread[TH2,5,main]
7
Thread[TH2,5,main]
9
Thread[TH2,5,main]
12
Thread[TH1,5,main]
16
Thread[TH1,5,main]
21
Thread[TH1,5,main]
27
Thread[TH1,5,main]
34
Thread[TH2,5,main]
38
Thread[TH2,5,main]
43
Thread[TH2,5,main]
49
Thread[TH2,5,main]
56
Thread[TH1,5,main]
64
Thread[TH1,5,main]
73
Thread[TH2,5,main]
81
Thread[TH2,5,main]
90
As TH1 starts with 0 and TH2 starts with 6, and many more instances of data corruption as far as this output is concern. So what went wrong here?? any guesses, okay, let me continue with my explanation here, as SamplePlotter class is having an instance level variable "j", and A extends SamplePlotter and the same instance of A is passed to Worker runnable instance and to the Threads, then both the threads are going to use this same instance of SamplePlotter, and eventually producing an output, which is not as expected. Now I think most of us might agree that in a multi-threaded environment/context, who is going to write SamplePlotter like this?? but assume that this SamplePlotter class is part of a JAR file that is distributed from a separate source and as developer you are not suppose to change the source of this class, but use it by extending this SamplePlotter class or any other wrapper. Is there any ways we can solve this coding or thread-safe related matter? So that both these Threads TH1 and TH2 will run, but separately and not try to use same instance of SamplePlotter, and so it's instance variable values. Having written this problem statement, I spent sometime on this and found one way to resolve this, this might be not an unique/only way to solve this problem, and one can suggest any other way of solving this and suggesting any design pattern as well. I just tried to separate the instance of SamplePlotter and provided both these Threads to work on separate instance/object of SamplePlotter, thus solving this stepping on one another stuff. So I created a wrapper and named it as SamplePlotterModified, and class A now extends SamplePlotterModified, instead of SamplePlotter, and the method signature remains the same, thus no code change required for the client test program and SamplePlotter class. SamplePlotterModified.java
import java.util.Hashtable;

class SamplePlotterModified 
{
  private Hashtable ht;
  public SamplePlotterModified() {
    if(ht == null)
      ht = new Hashtable();
  }
  public int setJ(int aj) {
    if(ht.get(Thread.currentThread().getName()) == null) {
      SamplePlotter sp =  new SamplePlotter();
      ht.put(Thread.currentThread().getName(),sp);
      return sp.setJ(aj);
    } else {
      SamplePlotter sp = (SamplePlotter) ht.get(Thread.currentThread().getName());
      return sp.setJ(aj);
    }
  }
}
this setJ method does some checking for the identifier, and here I have used the Thread name as identifier for these Threads. This method setj creates separate instance for each thread and passes on the result back, and in order to avoid repetitively creating SamplePlotter instance on separate setj method invocation, there is a Hashtable instance is used to store/pool these instances for use. client.java
public class  client
{
  public client() {
    A a = new A();
    Worker w = new Worker(a);
    Thread th = new Thread(w, "TH1");
    Thread th1 = new Thread(w, "TH2");
    th.start();
    th1.start();
  }
  public static void main(String[] args) 
  {
     new client();
  }
}
class Worker implements Runnable
{
  private A a;
  boolean st = false;
  public Worker(A a) {
    this.a = a;
  }
  public void run() {
    for(int i=0;i<10;i++) {
      if(Thread.currentThread().holdsLock(a)) {
       a.notify();
      }
    System.out.println(Thread.currentThread().toString()+"   ");
    a.print(i);
    try
    {
      if(Thread.currentThread().holdsLock(a)) {
       Thread.currentThread().yield();
      }
    } catch (Exception ex){
      ex.printStackTrace();
    }
    }
  }
};
Now un commenting those lines for the second thread and executing this test client program, following is the output as expected:
Thread[TH1,5,main]
0
Thread[TH1,5,main]
1
Thread[TH1,5,main]
Thread[TH2,5,main]
0
Thread[TH2,5,main]
1
Thread[TH2,5,main]
3
Thread[TH2,5,main]
3
Thread[TH1,5,main]
6
Thread[TH1,5,main]
10
Thread[TH1,5,main]
15
Thread[TH1,5,main]
6
Thread[TH2,5,main]
10
Thread[TH2,5,main]
15
Thread[TH2,5,main]
21
Thread[TH2,5,main]
28
21
Thread[TH1,5,main]
28
Thread[TH1,5,main]
36
Thread[TH1,5,main]
45
Thread[TH2,5,main]
36
Thread[TH2,5,main]
45
Now both TH1 and TH2, starts with 0 and ends with 45, and this actually solves this problem statement. I welcome all reader of this page to comment on this approach and suggest any improvement/drawback/workaround on these code and design aspect of this problem statement. You can reach me at usingframeworks @ gmail . com. Thanks for reading this !! Have an great coding time !! Feedback as sent by Guddu on 20 Nov 2010 : ............................................................................. Thanks for this approach discussed on this page. In my thinking there will be need for managing the entries in Hashtable, as I don't see any removal of the object after us. One can think it as a drawback as one may have to manage the Hashtable used as and when required or else size of this Hashtable will increase and could be potential problem in long run with an overhead of memory and performance. Instead you can use ThreadLocal instance to store variable per Thread and this way every Thread will have a separate instance of the common business object. This way you might not have to worry about managing a storage of instance and invalidating it when required. ............................................................................. If anything missed out , please let me know at techienjoy at yahoo . com
Thread Deadlock using Java :
Example reproducing a possible Thread 
using Java Technology.
Image creation using Java AWT :
In-Memory Image creation using AWT on Java Platform.
Thread wait and notify With Example :
Example using wait and notify within Thread 
with code and explained
Interview Questions and answer of Java Technology :
Interview Questions and answer of Java Technology.
List of Examples on Java Platform :
List of Examples on Java Platform.
Example of Drag and Drop using Java Technology :
Example of Drag and Drop using Java Technology.
Java Reflection using Comparator :
Comparator using Reflection on Java Platform
and example discussed.
Synchronized Block wait and notify With Example :
Example using wait and notify from within
synchronized block with code and explained
RMI and Java Stub and Skeleton :
Example using RMI using Java Technology.
Example ThreadPoolExecutor using Java :
ThreadPoolExecutor Example using Java Technology.
Thread design scenario using Java :
Thread design scenario using Java Technology.
Event Handling using Java Technology :
Example on how to use Event
and handling code using Java Technology.


References :
Tags: java comparator reflection
Tags: java example drag n drop
Tags: Java Interview Questions
Tags: java rmi tutorial stub skeleton
Tags: Java Thread Deadlock
Tags: Java Thread Design Scenarios
Tags: Java threadpoolexecutor
Tags: Java



DISCLAIMER :
The content provided in this page is not warranted and/or guaranteed by techienjoy.com. 
techienjoy.com is not liable for any negative consequences that may result/arise from 
implementing directly/indirectly any information covered in these pages/articles/tutorials.

All contents of this site is/are written and provided on an "AS IS" basis,
without WARRANTIES or conditions of any kind, either express or implied, including, without
limitation, merchantability, or fitness for a particular purpose. You are solely responsible
for determining the appropriateness of using or refering this and assume any risks associated
with this.

In spite of all precautions taken to avoid any typo in these pages, there might be some 
issues like grammatical mistakes and typos being observed in these pages, techienjoy.com
extends sincerest apologies to all our visitors for the same.



Android Examples || Android Examples

© Copyright 2010-2012, TECHIENJOY, All Rights Reserved.      Privacy Policy     Disclaimer & Terms & Conditions