让读者/作家线程进入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发生器可以发送新的号码之前多次。
我问的是:我如何实现与同步方法的锁,以便我不必使用睡眠方法?
答
下面是监视器最多保存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;
}
}
过宽:有很多方法可以做到这一点 –
你可以给我一些他们的? – petrogass