实现一个简单的生产者消费者模式
阻塞队列用在哪里?
- 生产者消费者模式
- 传统版(synchronized, wait, notify)
- 阻塞队列版(lock, await, signal)
- 线程池
- 消息中间件
示例代码
TraditionalProducerConsumerDemo.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;
class ShareData {
private int number = 0;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void increment() throws Exception{ lock.lock(); try { while(number != 0) { condition.await(); }
number++;
System.out.println(Thread.currentThread().getName() + "\t " + number);
condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } }
public void decrement() throws Exception{ lock.lock(); try { while(number == 0) { condition.await(); }
number--;
System.out.println(Thread.currentThread().getName() + "\t " + number);
condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }
public class TraditionalProducerConsumerDemo { public static void main(String[] args) {
ShareData shareData = new ShareData();
new Thread(() -> { for (int i = 0; i < 5; i++) { try { shareData.increment(); } catch (Exception e) { e.printStackTrace(); } } }, "t1").start();
new Thread(() -> { for (int i = 0; i < 5; i++) { try { shareData.decrement(); } catch (Exception e) { e.printStackTrace(); } } }, "t2").start(); } }
|
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| t1 1 t2 0 t1 1 t2 0 t1 1 t2 0 t1 1 t2 0 t1 1 t2 0 t1 1 t2 0 t1 1 t2 0 t1 1 t2 0 t1 1 t2 0 t1 1 t2 0
|
一些问题
多线程内判断为什么用wihle,而不是if?
由Object里面的wait方法介绍得知:
多线程里面,中断和虚假唤醒是可能的,这种wait方法应该
始终在循环中使用。
也就是说,被唤醒后,要被拉回来,重新判断一次,防止虚假唤醒。