尝试使用生产者和消费者模式打印斐波纳契系列

时间:2016-11-23 20:03:20

标签: java multithreading synchronization producer-consumer

我希望能够使用线程打印Fibonacci系列,所以我创建了2个线程:

根据公式f(n)= f(n-1)+ f(n-2)填充数组的生产者 将打印到目前为止已计算的元素的消费者

我将共享数组设置为每次只能存储5个元素,并且使用者将释放数组中的空间,允许生产者添加更多元素。

这是我的消费者代码:

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();
        }

    }
}

}

这是生产者代码:

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();
    }
}

}

和启动两个线程的主类:

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");
}

}

我的问题是:尝试运行之后,我得到一个无限循环,因为只要数组中有一个新项目,消费者就会获取它并释放空间,这意味着数组不能真正填充项目,因为消费者立即释放它。 我怎样才能使它发挥作用?

1 个答案:

答案 0 :(得分:1)

唯一“1”输出的新问题是因为.get()与第一个元素peekFirst相同,但它没有删除它!

我认为你想要的是System.out.print(sharedArray.pollFirst() + " ");,它会检索第一个元素并将其从链表中删除。

您的错误可能是因为您删除了一个节点,但您没有在生产者中更新n,然后指向错误的索引,因为每个删除的元素应该为-1。

编辑:您还应该检查的是,您的消费者不会删除所有元素,因为您需要至少2个来计算下一个斐波那契数字!

编辑2:类似

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

            }...

您需要在制作人中更新N,您可以将其更改为sharedArray.add(sharedArray.size(),sharedArray.size()-1+sharedArray.size()-2);,这样您就永远不会离开bounderys。 您可以这样做,因为您已经预先检查了是否达到了限制,并且根本不需要n

编辑3:

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

应该是

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

我的坏人应该提到......