尝试使用生产者和消费者模式打印斐波那契数列
trying to print a Fibonacci series using producer and consumer pattern
我希望能够使用线程打印斐波那契数列,所以我创建了 2 个线程:
生产者将根据公式 f(n) = f(n-1)+f(n-2) 填充数组
将打印到目前为止已计算的元素的消费者
我会将共享数组设置为一次只能存储5个元素,消费者将释放数组中的space,让生产者添加更多元素。
这是我的消费者代码:
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();
}
}
}
和启动两个线程的主要 class:
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");
}
}
我的问题是: 在尝试 运行 这个之后,我得到了一个无限循环,因为一旦数组中有一个新项目,消费者拿走它并释放 space,这意味着数组不能真正填充项目,因为消费者会立即释放它。
我怎样才能让它发挥作用?
只有“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));
我的错应该提到....
我希望能够使用线程打印斐波那契数列,所以我创建了 2 个线程:
生产者将根据公式 f(n) = f(n-1)+f(n-2) 填充数组 将打印到目前为止已计算的元素的消费者
我会将共享数组设置为一次只能存储5个元素,消费者将释放数组中的space,让生产者添加更多元素。
这是我的消费者代码:
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();
}
}
}
和启动两个线程的主要 class:
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");
}
}
我的问题是: 在尝试 运行 这个之后,我得到了一个无限循环,因为一旦数组中有一个新项目,消费者拿走它并释放 space,这意味着数组不能真正填充项目,因为消费者会立即释放它。 我怎样才能让它发挥作用?
只有“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));
我的错应该提到....