0

I am making Bean as a singleton class, where i have setter and getter for bean.ThreadA and ThreadB using the singleton object of Bean. I want ThreadA should perform its task first and then ThreadB should start its execution. I am getting inconsistent . I have my doubts whether my code is improper or how can i make my code completely thread safe. Hoping for the cooperation.

public class Test {
    public static void main(String args[])
    {
        Bean bean = Bean.getInstance();
        new ThreadA(bean);
        new ThreadB(bean);
    }
}
class Bean
{   
    private static Bean instance = null;
    protected Bean() {
        // TODO Auto-generated constructor stub
    }
    int x;
    public static Bean getInstance()
    {
        if(instance==null)
        {
            instance=new Bean();
            synchronized (instance) {
                instance=new Bean();

            }
        }
        return instance;
    }
    public  synchronized int getX() {
        return x;
    }

    public synchronized void  setX(int x) {
        this.x = x;
    }

}
class ThreadA extends Thread
{
    Bean  b;
    public ThreadA(Bean b) {
        this.start();
        this.b=b;
    }
    @Override
    public void run() {
        for (int i=1;i<=10;i++)
        {
            this.b.setX(i);
            System.out.println(Thread.currentThread().getName() + " "+this.b.getX());

        }
    }
}

class ThreadB extends Thread
{
    Bean b;
    public ThreadB(Bean b) {
        this.start();
        this.b=b;
    }
    @Override
    public void run() {
        for (int i=1;i<=10;i++)
        {
            this.b.setX(i);
            System.out.println(Thread.currentThread().getName() +" "+ this.b.getX());
        }
    }
}

Thread-0 1 Thread-0 2 Thread-0 3 Thread-0 4 Thread-0 5 Thread-0 6 Thread-1 1 Thread-0 7 Thread-1 2 Thread-1 3 Thread-1 4 Thread-1 5 Thread-0 8 Thread-1 6 Thread-1 7 Thread-1 8 Thread-1 9 Thread-1 10 Thread-0 9 Thread-0 10

I am getting inconsistent result like above . I want My Thread-0 which is ThreadA should perform the task first and then ThreadB = Thread-1 should start it's execution.

/////////////////////////////my changed code starts below

package p1;

public class T {
    public static void main(String args[])
    {
      Bean1 bean = Bean1.getBean1();

      new ThreadA(bean);
    // bean.lock(true);
      new ThreadB(bean);
    }
}
class Bean1
{   
    private static Bean1 instance = null;
     static boolean threadAFinished=false;
    private Bean1() {
    }
    private boolean beanLocked;

    synchronized public void lock (boolean b) {
        if(b)
        {
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        beanLocked=b;
    }
    synchronized public boolean getLock()
    {
        if(!beanLocked)
        {
            notify();
        }

        return beanLocked;
    }
   int x;
    public static Bean1 getBean1() {
        if (instance==null) {
            instance=new Bean1();
        }
        return instance;
    }
    public  int getX() {

        return x;
    }

    public  void  setX(int x) {

        this.x = x;
    }
}
    class ThreadA implements Runnable {
        Bean1  b;
        public ThreadA(Bean1 b) {
            this.b=b;
        new Thread (this).start(); // run() uses b, set it before starting the thread

        }
        @Override
        public void run() {
            for (int i=1;i<=10;i++) {
                b.setX(i);
                System.out.println(Thread.currentThread().getName() + " "+b.getX());

        }
           b.threadAFinished=true;
          b.lock(false);
         b.getLock();
    }

    }

    class ThreadB implements Runnable {
        Bean1 b;
        public ThreadB(Bean1 b) {
            this.b=b;
            new Thread(this).start();

        }
        @Override
        public void run() {
        if(!b.threadAFinished)
        {
        b.lock(true);
        }
            for (int i=1;i<=10;i++) {
                b.setX(i);
                System.out.println(Thread.currentThread().getName() +" "+ b.getX());
    }
            }
        }
Cœur
  • 37,241
  • 25
  • 195
  • 267
  • Didn't you just ask this question? [here](http://stackoverflow.com/q/15318684/522444) – Hovercraft Full Of Eels Mar 10 '13 at 04:47
  • I guess you need a [BlockingQueue](http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html) – Amit Deshpande Mar 10 '13 at 04:51
  • I am new user here. I asked this question in improper way, so it got closed. This time i have tried to put this question in better way, so others can understand :) – user1778203 Mar 10 '13 at 04:51
  • in stead of using BlockingQue the existing approach can be enhanced ? – user1778203 Mar 10 '13 at 04:55
  • 3
    [PLEASE don't start threads in constructor](http://stackoverflow.com/questions/5623285/java-why-not-to-start-a-thread-in-the-constructor-how-to-terminate) – Oleg Mikheev Mar 10 '13 at 04:59
  • @OlegMikheev ok ill make that change and observe the difference :) – user1778203 Mar 10 '13 at 05:02
  • @OlegMikheev Thread-0 1 Thread-0 2 Thread-0 3 Thread-0 4 Thread-0 5 Thread-0 6 Thread-0 7 Thread-0 8 Thread-0 9 Thread-0 10 Thread-1 1 Thread-1 2 Thread-1 3 Thread-1 4 Thread-1 5 Thread-1 6 Thread-1 7 Thread-1 8 Thread-1 9 Thread-1 10 – user1778203 Mar 10 '13 at 05:06
  • There will be no difference hopefully, it's just a thing to keep in mind in the future... your task can't be solved with your approach - thread 0 will finish executing setX before thread 1 is even created and you can't control that kind of stuff – Oleg Mikheev Mar 10 '13 at 05:06
  • @OlegMikheev I got desired result but next time when i ran the program i got inconsistent result again. – user1778203 Mar 10 '13 at 05:07
  • @OlegMikheev this is something related to how Java Memory Model and JVM works ? – user1778203 Mar 10 '13 at 05:09
  • yes, and it works differently on different implementations, even if you manage to ensure right timing on your implementation if can easily fail on different implementation, you should take a look at [java.util.concurrent](http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html), select the right pattern and either use it or re-implement depending on your task – Oleg Mikheev Mar 10 '13 at 05:12
  • @OlegMikheev i ll try to implement this in different manner :) Thanks .. – user1778203 Mar 10 '13 at 05:15

1 Answers1

2

There are 2 issues here - making a class singleton and thread synchronization. Moreover, I think you are using some unnecessary this and synchronized keywords. I wrote a quick and dirty edit of your code, hope this helps.

public class P4 {

    public static void main(String args[])
    {
        Bean bean = Bean.getBean();
        new ThreadA(bean);
    bean.lock(true, true);
        new ThreadB(bean);
    }
}

class Bean
{   
    private static Bean instance = null;
    private Bean() {
    }

    int x;
    public static Bean getBean() {
        if (instance==null) {
            instance=new Bean();
        }
        return instance;
    }

    private boolean beanLocked;
    synchronized public boolean lock (boolean b, boolean l) {
    if (b) {
        beanLocked = l;
        notify();
    } else {
        while (beanLocked) {
        try {
            wait();
        } catch (InterruptedException ex) {
    }}}
    return beanLocked;
    }

    public int getX() {
        return x;
    }

    public void  setX(int x) {
        this.x = x;
    }

}

class ThreadA implements Runnable {
    Bean  b;
    public ThreadA(Bean b) {
        this.b=b;
    new Thread (this).start(); // run() uses b, set it before starting the thread
    }
    @Override
    public void run() {
        for (int i=1;i<=10;i++) {
            b.setX(i);
            System.out.println(Thread.currentThread().getName() + " "+b.getX());

    }
    b.lock(true, false);
}}

class ThreadB implements Runnable {
    Bean b;
    public ThreadB(Bean b) {
        this.b=b;
        new Thread(this).start();
    }
    @Override
    public void run() {
    b.lock(false, false);   // Dont care about 2nd argument
        for (int i=1;i<=10;i++) {
            b.setX(i);
            System.out.println(Thread.currentThread().getName() +" "+ b.getX());
}}}
Manidip Sengupta
  • 3,573
  • 5
  • 25
  • 27
  • @ManidipSengupta I have recently edit the code. i feel the wait() method that you apply was never getting called in any case. In my changes wait() n notify() both getting called .Both the answers are right still i need your approval for my code whether its fullproof or not .. :) . We will exchange more info this way :) – user1778203 Mar 11 '13 at 08:26
  • @user1778203 Hey you absolutely do not need my approval to do anything. I am glad you figured out what works for you. The wait/notify pair is very commonly used for thread management. I will look into your changes later (btw, where is it?) – Manidip Sengupta Mar 11 '13 at 16:05
  • @ManidipSengupta Please check the second code,which is changed one where main method is in class T :) – user1778203 Mar 11 '13 at 20:50
  • @1778203 I am afraid I do not quite follow your logic here. The main() method is OK. Now, I suppose you want ThreadA to complete and then ThreadB to start. FIrstly, I would not access a class variable like b.threadAFinished = true; It essentially does the same thing as b.lock(false), but we need to call a b.lock(true) before calling ThreadB (you never do). Moreover, ThreadA should have nothing to do with b.getLock(), it's already done with its stuff! In summary: work out the logic (for both threads) [1] Wait till you can lock Bean1 [2] do you stuff [3] Release the lock – Manidip Sengupta Mar 11 '13 at 23:42
  • @ManidipSengupta I am little puzzled by your answer.I have declared threadAFinished boolean variable just to ensure my threadA finish first. Do you mean to say is it not a good practice to declare class variable in this case? if its not please elaborate .:) – user1778203 Mar 12 '13 at 06:15
  • user1778203: I put a new version of the code below your question - take a look at it. Note the following points: (1) ThreadA and ThreadB do the same thing, so refactor them into a single class (2) Start indexing loops from 0 (not 1), becomes more readable by Java programmers (3) bean is locked in the main thread so that A executes before B (4) padlock is an internal variable, not accessed outside of Bean class (5) There is no polling (looping to check for a condition). (6) Read up some Java tutorials on Java concurrency for alternative implementations. – Manidip Sengupta Mar 12 '13 at 13:35
  • @ManidipSengupta i cant see the latest code Sir. You can mail me the code at abhishek.kanekar@gmail.com – user1778203 Mar 12 '13 at 21:25