我希望能够使用线程打印斐波那契数列,所以我要创建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”输出的新问题是,因为.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);
,这样您就永远不会陷入困境。可以这样做是因为您已经事先检查了是否达到限制,并且根本不需要
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));
我的坏人应该提到...。
关于java - 尝试使用生产者和消费者模式打印斐波那契数列,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40773236/