wannabe programmer wannabe programmer - 13 days ago 4
Java Question

trying to print a Fibonacci series using producer and consumer pattern

I want to be able to print Fibonacci series using threads, so I'm creating 2 threads:

A producer which will fill the array according to the formula f(n) = f(n-1)+f(n-2)
A consumer that will print the elements that has been calculated so far

I will set the shared array to be able to store only 5 elements at time, and the consumer will free up space in the array, allowing the producer to add more elements.

This is my consumer code:

public class Consumer implements Runnable
{
private LinkedList<Integer> sharedArray;

public Consumer(LinkedList<Integer> array, int size, int series)
{
sharedArray = array;

}

@Override
public void run()
{
while (true)
{
try
{
print();
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

private void print() throws InterruptedException
{
while (true)
{
synchronized (sharedArray)
{
while (sharedArray.isEmpty())
{
try
{
sharedArray.wait();
} catch (Exception ex)
{
ex.printStackTrace();
}

}
System.out.print(sharedArray.get(0) + " ");
sharedArray.notifyAll();
}

}
}

}


And this is the producer code:

public class Producer implements Runnable

{
private LinkedList<Integer> sharedArray;
private int sharedArraySize;
private int seriesSize;

public Producer(LinkedList<Integer> array, int size, int series)
{
sharedArray = array;
sharedArraySize = size;
seriesSize = series;

}

@Override
public void run()
{
for (int i = 0; i < seriesSize; i++)
{
try
{
calculate(i);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

private void calculate(int n) throws InterruptedException
{
synchronized (sharedArray)
{
while (sharedArray.size() == sharedArraySize)
{
sharedArray.wait();
}
if (n == 0 || n == 1)
{
sharedArray.add(n, 1);
} else
{
sharedArray.add(n, sharedArray.get(n - 1) + sharedArray.get(n - 2));
}
sharedArray.notifyAll();
}
}

}


and the main class that starts both of the threads:

public class FibThreads

{


public static void main(String[] args)
{
int seriesSize = 18; //Integer.parseInt(args[0]);
int elementsInLine = 0;//Integer.parseInt(args[1]);
int sharedArraySize = 5;//Integer.parseInt(args[2]);

LinkedList<Integer> sharedArray = new LinkedList<Integer>();

Thread producer = new Thread(new Producer(sharedArray,sharedArraySize,seriesSize), "Producer");
Thread consumer = new Thread(new Consumer(sharedArray,sharedArraySize,seriesSize), "Consumer");
producer.start();
consumer.start();
System.out.println("End of main");
}

}


My problem is: After trying to run this, I get an infinite loop, because as soon as there is a new item in the array, the consumer takes it and free up space, which means the array can't really be filled with items because the consumer frees it immediately.
How can I make it work?

Answer

Your new problem with the only "1" output is because .get() does the same like peekFirst you get the first element but it does not remove it!

What I assume you want is System.out.print(sharedArray.pollFirst() + " "); which retrives the first element and removes it from the linked list.

Your Error was probably because you removed a node but you did not updated n in your producer which then pointed to the wrong index as it should be -1 for every removed element.

EDIT: Something you should also check is that your consumer does not remove all elements as you need at least 2 to calculate the next fibonacci number!

EDIT 2: something like

while (sharedArray.isEmpty()||sharedArray.size()<=2)
            {
                try
                {
                    sharedArray.wait();
                } catch (Exception ex)
                {
                    ex.printStackTrace();
                }

            }...

And you need update N in your producer, you could change it to sharedArray.add(sharedArray.size(),sharedArray.size()-1+sharedArray.size()-2); so you would never go out of bounderys. You can do this because you already check beforehand if you reached the limitation and n isn't needed at all.

EDIT 3:

sharedArray.add(sharedArray.size(),sharedArray.size()-1+sharedArray.size()-2);

should be

sharedArray.add(sharedArray.size(),sharedArray.get(sharedArray.size()-1)+sharedArray.get(sharedArray.size()-2));

My bad should have mentioned that....