0

我将 Bean 制作为单例类,其中我使用 Bean 的单例对象为 bean.ThreadA 和 ThreadB 设置了 setter 和 getter。我希望 ThreadA 应该首先执行它的任务,然后 ThreadB 应该开始它的执行。我越来越不一致。我怀疑我的代码是否不正确,或者如何使我的代码完全线程安全。期待合作。

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 线程 1 6 线程 1 7 线程 1 8 线程 1 9 线程 1 10 线程 0 9 线程 0 10

我得到的结果与上面的不一致。我希望我的 Thread-0 是 ThreadA 应该首先执行任务,然后 ThreadB = Thread-1 应该开始它的执行。

/////////////////////////我更改的代码从下面开始

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

1 回答 1

2

这里有两个问题 - 制作一个类单例和线程同步。此外,我认为您使用了一些不必要的 this 和 synchronized 关键字。我对您的代码进行了快速而肮脏的编辑,希望对您有所帮助。

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());
}}}
于 2013-03-10T05:14:14.767 回答