我的关注 |
¥0 java如何用代码模拟生产者-消费者?
0

java如何用代码模拟生产者-消费者?

大智若愚
修改
评论(0)
1个回答
0
采纳

生产者-消费者问题一般是,有一个缓冲区,它支持 put 和 take 方法。如 果试图在空的缓冲区上执行 take 操作,则在某一个项变得可用之前,线程将一 直阻塞;如果试图在满的缓冲区上执行 put 操作,则在有空间变得可用之前, 线程将一直阻塞。可以在单独的等待集合中保存 put 线程和 take 线程,这样就 可以在缓冲区中的项或空间变得可用时利用最佳规划,一次只通知一个线程。可 以使用两个 Condition 实例来做到这一点。

下面是缓冲区类 LockedBuffer,在这个类的 put 和 take 方法中使用了可重入 锁与条件变量:
  1. package conditionlock;
  2. import java.util.concurrent.locks.Condition;
  3. import java.util.concurrent.locks.Lock;
  4. import java.util.concurrent.locks.ReentrantLock;
  5. public class LockedBuffer {
  6. // 可重入锁
  7. final Lock lock = new ReentrantLock();
  8. // 两个条件对象
  9. final Condition notFull = lock.newCondition();
  10. final Condition notEmpty = lock.newCondition();
  11. // 缓冲区
  12. final Object[] items = new Object[10];
  13. int putptr, takeptr, count;// 计数器
  14. // 放数据操作,生产者调用该方法
  15. public void put(Object x) throws InterruptedException {
  16. lock.lock();
  17. try {
  18. // 如果缓冲区满了,则线程等待 while (count == items.length)
  19. notFull.await();
  20. items[putptr] = x;
  21. if (++putptr == items.length)
  22. putptr = 0;
  23. ++count;
  24. // 向消费者线程发送通知
  25. notEmpty.signal();
  26. } finally {
  27. lock.unlock();
  28. }
  29. }
  30. // 消费者线程调用该方法
  31. public Object take() throws InterruptedException {
  32. lock.lock();
  33. try {
  34. // 如果缓冲区空,则等待 while (count == 0)
  35. notEmpty.await();
  36. Object x = items[takeptr];
  37. if (++takeptr == items.length)
  38. takeptr = 0;
  39. --count;
  40. // 通知其他生产者线程 notFull.signal();
  41. return x;
  42. } finally {
  43. lock.unlock();
  44. }
  45. }
  46. }
生产者:
  1. package conditionlock;
  2. //生产者
  3. class Producer implements Runnable {
  4. LockedBuffer buffer;
  5. public Producer(LockedBuffer buf) {
  6. buffer = buf;
  7. }
  8. public void run() {
  9. char c;
  10. for (int i = 0; i < 20; i++) {
  11. c = (char) (Math.random() * 26 + 'A');
  12. try {
  13. // 向缓冲区放入数据
  14. buffer.put(c);
  15. } catch (InterruptedException e1) {
  16. e1.printStackTrace();
  17. }
  18. System.out.println("Produced: " + c);
  19. try {
  20. Thread.sleep((int) (Math.random() * 100));
  21. } catch (InterruptedException e) {
  22. }
  23. }
  24. }
  25. }
消费者
  1. package conditionlock;
  2. //生产者
  3. class Producer implements Runnable {
  4. LockedBuffer buffer;
  5. public Producer(LockedBuffer buf) {
  6. buffer = buf;
  7. }
  8. public void run() {
  9. char c;
  10. for (int i = 0; i < 20; i++) {
  11. c = (char) (Math.random() * 26 + 'A');
  12. try {
  13. // 向缓冲区放入数据
  14. buffer.put(c);
  15. } catch (InterruptedException e1) {
  16. e1.printStackTrace();
  17. }
  18. System.out.println("Produced: " + c);
  19. try {
  20. Thread.sleep((int) (Math.random() * 100));
  21. } catch (InterruptedException e) {
  22. }
  23. }
  24. }
  25. }
测试类

package conditionlock;

public class LockConditionTest {
public static void main(String args[]) {
LockedBuffer stack = new LockedBuffer(); // 创建生产者,消费者
int count = 3;
Producer[] producers = new Producer[count];
Consumer[] consumers = new Consumer[count];
for (int i = 0; i < count; i++) {
producers[i] = new Producer(stack);
consumers[i] = new Consumer(stack);
}
for (int i = 0; i < count; i++) {
new Thread(producers[i]).start();
new Thread(consumers[i]).start();
}
}
}

程序运行结果如下:

Produced: Z
Consumed: Z
Produced: X
Consumed: X
…..
Produced: D
Produced: N
Produced: L
Produced: U
Produced: G
Produced: V
Consumed: Q
Produced: Q
Produced: U
Consumed: M
Produced: I
Consumed: D
….
Consumed: U
Produced: M
Consumed: G
Produced: P
Consumed: V
Produced: N
Consumed: Q
Produced: J
Consumed: U
Produced: L
……
Produced: Y
Consumed: O
Produced: E
Consumed: M
Produced: I
Consumed: P

采纳答案
大智若愚
修改
评论 (0)
撰写回答