2012-09-13 163 views
0

我有一个麻烦与三个线程共享一个资源...的Java多线程同步

public class Subject{ 

     int i; 
     boolean valueSet1 = false; 
     boolean valueSet2 = true; 
     boolean valueSet3 = true; 

    void put(int i){ 

     while(valueSet1){ 
      try{ 
       wait(); 
       }catch(InterruptedException e){ 
        System.out.println("Producer thread interrupted"); 
       } 
      } 
      System.out.println("Producer thread wakesup"); 
      valueSet1=true; 
      valueSet2=false; 
      this.i=i;   
      System.out.println("Put: "+i); 
      notify(); 
     } 


    void makesquare(){ 

      int a; 
      while(valueSet2){ 
       try{ 
        System.out.println("Convertor thread goin to sleep"); 
        wait(); 
       }catch(InterruptedException e){ 
        System.out.println("Convertor thread interrupted"); 
       } 
      }  
      System.out.println("Convertor thread wakesup"); 
      valueSet2 = true; 
      valueSet3=false; 
      a = this.i; 
      this.i = a*a; 
      System.out.println("Made: "+i);   
      notify(); 
    } 

    void get(){ 

      while(valueSet3){ 
       try{ 
        System.out.println("Consumer thread goin to sleep");     
        wait(); 
       }catch(InterruptedException e){ 
        System.out.println("Consumer thread interrupted"); 
       } 
      } 
      System.out.println("Consumer thread wakesup"); 
      valueSet3 = true; 
      valueSet1 = false; 
      System.out.println("Got: "+i); 
      notify();  
    } 

    } 

    class Producer implements Runnable{ 

     Subject q;  
     Thread t; 
     String msg; 
     Producer(Subject q, String msg){ 
      this.q=q; 
      this.msg = msg; 
      t = new Thread(this, this.msg); 
     } 
     @Override 
     public void run(){ 
      int i=2; 
      while(true){ 
       synchronized(q){ 
       q.put(i++); 
       } 
      } 
     } 
    } 
    class Consumer implements Runnable{ 

     Subject q;  
     Thread t; 
     String msg; 
     Consumer(Subject q,String msg){ 
      this.q = q; 
      this.msg = msg; 
      t = new Thread(this, this.msg); 
     } 
     @Override 
     public void run(){ 
      while(true){ 
       synchronized(q){ 
       q.get(); 
       } 
      } 
     } 
    } 

    class Convertor implements Runnable{ 
     Subject q; 
     Thread t; 
     String msg; 
     Convertor(Subject q, String msg){ 
      this.q=q; 
      this.msg = msg; 
      t = new Thread(this, this.msg);  
     } 
     @Override 
     public void run(){ 
      while(true){ 
       synchronized(q){ 
       q.makesquare(); 
       } 
      } 
     } 
    } 

有三个线程的程序。一个线程产生另一个产生量的平方。而最后一个线程消耗平方的产品。它们都共享相同的对象。

public class Thread3way { 

     public static void main(String[] args) { 
      Subject q = new Subject(); 
      Producer P = new Producer(q, "producer"); 
      Convertor Cv = new Convertor(q, "convertor"); 
      Consumer Cs = new Consumer(q, "consumer"); 
      P.t.start(); 
      Cv.t.start(); 
      Cs.t.start(); 
     } 
    } 
+6

什么问题? – Dave

+1

欢迎使用stackoverflow。请编辑您的帖子,以显示更多关于正在发生的事情的信息。你看到或失去了什么输出或行为?如果有例外,请务必添加它。 – Gray

+1

为什么不使用notifyAll()而不是notify()(因为您正在同步3个线程) –

回答

0

wait循环不是很正确,你需要不断循环,直到你的病情是真实的你做任何修改。我会做这样的(使用State枚举让事情更清晰):

public class Subject { 
    static enum State { EMPTY, WAITING_TO_SQUARE, WAITING_TO_GET }; 
    State state; 
    int value; 

    public synchronized void put(int i) { 
     while (state != State.EMPTY) { 
      try { 
       wait(); 
      }catch(InterruptedException e) { 
       System.out.println("Put interrupted"); 
      } 
     } 
     value = i; 
     state = State.WAITING_TO_SQUARE; 
    } 
} 

作为一个评论者指出的那样,你不需要同步两次,无论是synchronized(q)围绕Subject电话,申报你的方法​​。你不需要两个。

无需使用Runnables明确,只是让ProducerConvertorConsumerThread小号直接。那么你不需要t字段,你可以像P.start()那样启动线程。

+0

非常感谢哟..但我不明白“没有必要... P.start()”的声明..如何在没有可运行的情况下实现? – Tej

+0

@Tej:你可以从'Thread'继承'Producer',然后执行'Producer p = new Producer(...); p.start();'。 'Thread'实现'Runnable',这样你的'run'方法会在'p'开始时被调用。 –

0

听起来对我来说就像你正在做某种管道,有3个阶段。为什么不享受ExecutorService的好处:

class ConvertorTask implements Runnable { 

    private int number; 
    private static ExecutorService consumer = Executors.newSingleThreadExecutor(); 

    public ConvertorTask(int number) { 
     this.number = number;  
    } 

    public void run() { 
     consumer.submit(new ConsumerTask(number * number)); 
    } 
} 

class ConsumerTask implements Runnable { 

    private int number; 

    public ConsumerTask(int number) { 
     this.number = number;  
    } 

    public void run() { 
     System.out.println(number); 
    } 
} 

class Producer implements Runnable { 

    private ExecutorService convertor = Executors.newSingleThreadExecutor(); 

    public void run() { 
     int i = 0; 
     while(true) {   
      convertor.submit(new ConvertorTask(i++)); 
     } 
    } 
} 

public class Test { 

    public static void main(String[] args) throws InterruptedException {   
     Thread t = new Thread(new Producer()); 
     t.start(); 
    } 
}