简体   繁体   中英

I am trying to learn about Singleton class in java and multithreading

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM