2013-03-10 49 views
0

我使Bean成为一个单例类,其中我使用Bean的单例对象为bean.threadA和ThreadB设置了setter和getter。我希望ThreadA应该先执行它的任务,然后ThreadB应该开始执行它。我变得不一致。我怀疑我的代码是否不正确,或者如何让我的代码完全线程安全。希望合作。我想了解java和多线程中的Singleton类

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

线程0 1线程0 2线程0 3线程0 4线程0 5线程0 6线程1 1线程0 7线程1 2主题-1 3线程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

我得到的结果与上面不一致。我想我的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()); 
    } 
      } 
     } 
+0

难道你不问这个问题吗? [here](http://stackoverflow.com/q/15318684/522444) – 2013-03-10 04:47:12

+0

我想你需要[BlockingQueue](http://docs.oracle.com/javase/6/docs/api/java/util/并发/ BlockingQueue.html) – 2013-03-10 04:51:41

+0

我是新用户。我以不正确的方式问了这个问题,所以它关闭了。这次我试图用更好的方式提出这个问题,所以其他人可以理解:) – user1778203 2013-03-10 04:51:50

回答

2

这里有2个问题 - 创建一个单独的类和线程同步。此外,我认为你正在使用一些不必要的这个和同步的关键字。我写了一个快速而且脏的代码编辑,希望这有助于。

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

它现在运作良好:)感谢您的帮助:) – user1778203 2013-03-10 05:29:15

+0

@ManidipSengupta我最近编辑的代码。我觉得你应用的wait()方法在任何情况下都不会被调用。在我的修改中wait()n notify()都被调用了。两个答案都是正确的,我仍然需要你的批准,不管它是否全密或者不。.. :)。我们将通过这种方式交换更多信息:) – user1778203 2013-03-11 08:26:10

+0

@ user1778203嘿,你绝对不需要我的批准就可以做任何事情。我很高兴你明白什么对你有用。等待/通知对非常常用于线程管理。我会在稍后看看你的变化(顺便说一下,它在哪里?) – 2013-03-11 16:05:01