0

Beanをシングルトンクラスとして作成しています。ここでは、Beanのシングルトンオブジェクトを使用して、bean.ThreadAとThreadBのセッターとゲッターがあります。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());
        }
    }
}

スレッド-01スレッド-02スレッド-03スレッド-04スレッド-05スレッド-06スレッド-11スレッド-07スレッド-12スレッド-13スレッド-14スレッド-15スレッド- 08スレッド-16スレッド-17スレッド-18スレッド-19スレッド-10スレッド-09スレッド-010

上記のように一貫性のない結果が得られます。ThreadAであるMyThread-0が最初にタスクを実行し、次に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

ここには 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 に答える