I have a circular buffer (array/first in first out), a consumer and a producer. A producer puts random numbers into the array, and a consumer takes the first number and checks if it is relative prime.
My code works, and I think it works correct, but I want to improve it. I am not really sure about my "void run" methods. Should I anywhere else do the exception handling? Change the "infinite loop"? The method signatures should not be changed (they are predefined).
I would be happy about each suggestion to improve the code. (Don't care the visibility (public,...), and static things, I've just put it together in one file.
import java.math.BigInteger;
import java.util.Random;
public class ConsProd {
static class CircularBuffer {
private BigInteger[] buffer;
//"pointers"
private int read;
private int write;
public CircularBuffer(int size) {
this.buffer = new BigInteger[size];
this.read = 0;
this.write = 0;
}
public boolean isFull() {
for(int i = 0; i < buffer.length; i++) {
if(buffer[i] == null)
return false;
}
return true;
}
public boolean isEmpty() {
for(int i = 0; i < buffer.length; i++) {
if(buffer[i] != null)
return false;
}
return true;
}
public synchronized void put(BigInteger element) throws InterruptedException {
while(isFull()){
wait();
}
buffer[write] = element;
write = (write+1)%buffer.length;
notifyAll();
}
public synchronized BigInteger take() throws InterruptedException {
while(isEmpty()){
wait();
}
BigInteger temp = buffer[read];
buffer[read] = null;
read = (read+1)%buffer.length;
notifyAll();
return temp;
}
}
static class Consumer implements Runnable {
private int id;
private CircularBuffer buffer;
public Consumer(int id, CircularBuffer b) {
this.id = id;
this.buffer = b;
}
private void consume(BigInteger e) {
synchronized(e){
System.out.println("consumer " + id + " retrieved: " + e);
if (e.isProbablePrime(100)) {
System.out.println(" -----> probably prime!");
}
}
}
@Override
public void run() {
try { // TODO is this the right place to handle the exception?
while (!Thread.currentThread().isInterrupted()) {
BigInteger e = buffer.take();
consume(e);
}
} catch (InterruptedException e) { }
}
}
static class Producer implements Runnable {
private int id;
private CircularBuffer buffer;
public Producer(int id, CircularBuffer b) {
this.id = id;
this.buffer = b;
}
protected BigInteger produce() {
BigInteger x = new BigInteger(10, new Random());
System.out.println("producer " + id + " produced: " + x.toString());
return x;
}
@Override
public void run() {
try { // TODO is this the right place to handle the exception?
while (!Thread.currentThread().isInterrupted()) {
BigInteger e = produce();
buffer.put(e);
}
} catch (InterruptedException e) { }
}
}
public static void main(String[] args) {
CircularBuffer cbuf = new CircularBuffer(4);
Thread t1 = new Thread(new Consumer(1, cbuf));
Thread t2 = new Thread(new Consumer(2, cbuf));
Thread t3 = new Thread(new Consumer(3, cbuf));
Thread t4 = new Thread(new Producer(1, cbuf));
Thread t5 = new Thread(new Producer(2, cbuf));
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}