让读者/作家线程进入R/W/R/W

问题描述:

我得到了一份家庭作业,我必须实现一个Generator线程(编写器),它发送从0开始的数字序列到N个平均线程(读者) 0进入Avg_0,1进入Avg_1,N再次进入Avg_0,依此类推。一旦Avg线程接收到M个数字,它们就会计算它们的平均值并将其发送到输出中。让读者/作家线程进入R/W/R/W

Here u能看到我的代码,我使用的显示器类作为数据库所在的线程可以写入和从安全

而现在,一切运行顺利读取,但你可以看到我用了两个了Thread.sleep( )以确保读写器以W/R/W/R/W ...的顺序工作,否则我总是会看到发生器在数据库上多次写入数据,然后Avgs才能读取或输出Avgs发生器可以发送新的号码之前多次。

我问的是:我如何实现与同步方法的锁,以便我不必使用睡眠方法?

+0

过宽:有很多方法可以做到这一点 –

+0

你可以给我一些他们的? – petrogass

下面是监视器最多保存N个值的一种方法,平均值是在Avg类中计算的,发生器只是向监视器发送一串数字。睡眠不是必需的,但我保留了一个,以便我们可以读取输出。

public class Main { 

    public static void main(String[] args) { 
     int N=2; 
     int M=3; 

     Monitor m = new Monitor(N); 

     Generator g = new Generator(m); 
     g.start(); 

     Avg[] avg = new Avg[N]; 
     for (int i=0; i<N; i++){ 
      avg[i]=new Avg(i, m, M); 
      avg[i].start(); 
     } 
    } 
} 

class Generator extends Thread { 
    private final Monitor m; 

    public Generator(Monitor m) { 
     this.m = m; 
    } 

    @Override 
    public void run() { 
     int i= 0; 
     try { 
      do { 
       m.doWrite(i); 
       ++i; 
       Thread.sleep(500); 
      } while (true); 
     } catch (InterruptedException ie) { 
     } 
    } 
} 

class Avg extends Thread { 
    private final int id; 
    private final Monitor m; 
    private final int M; 

    public Avg(int id, Monitor m, int M) { 
     this.id = id; 
     this.m = m; 
     this.M = M; 
    } 

    @Override 
    public void run() { 
     try { 
      do { 
       double sum = 0; 
       for (int i = 0; i < M; ++i) { 
        sum += m.doRead(id); 
       } 
       double avg = sum/M; 
       System.out.println("Avg " + id + " : " + avg); 
      } while (true); 
     } catch (InterruptedException ie) { 
     } 
    } 
} 

class Monitor { 
    private final Integer[] numbers; 
    private int current; 

    public Monitor(int N) { 
     numbers = new Integer[N]; 
    } 

    public synchronized void doWrite(int i) throws InterruptedException{ 
     while (numbers[current] != null) { 
      wait(); 
     } 
     numbers[current]=i; 
     current = (current+1)%numbers.length; 
     notifyAll(); 
    } 

    public synchronized int doRead(int id) throws InterruptedException{     
     while (numbers[id] == null) { 
      wait(); 
     } 
     int result = numbers[id]; 
     numbers[id] = null; 
     notifyAll(); 
     return result; 
    } 
} 
+0

哇,不期待这样一个完整的答案,非常感谢你! 你能告诉我为什么需要睡眠吗?我试着评论它,该程序根本没有输出 – petrogass

+0

@petrogass抱歉,我犯了一个错误:我忘记了doRead中的notifyAll。现在纠正了。 –

+0

我应该将电流初始化为0还是没有必要? – petrogass