生产者消费者模式
一、synchronized同步
public class PcSync {
static int MAX = 10 ;
static Queue< Object> queue = new ArrayDeque < > ( MAX) ;
public static void main ( String[ ] args) {
Producer p = new Producer ( ) ;
Consumer c1 = new Consumer ( ) ;
Consumer c2 = new Consumer ( ) ;
new Thread ( p) . start ( ) ;
new Thread ( p) . start ( ) ;
new Thread ( c1) . start ( ) ;
new Thread ( c2) . start ( ) ;
}
static class Producer implements Runnable {
@Override
public void run ( ) {
while ( true ) {
synchronized ( PcSync. class ) {
if ( queue. size ( ) < MAX) {
queue. add ( new Object ( ) ) ;
System. out. println ( "生产一个,生产后有商品" + queue. size ( ) + "个" ) ;
SleepTools. randomMs ( 400 ) ;
} else {
System. out. println ( "满了,不能再生产了..." ) ;
}
}
}
}
}
static class Consumer implements Runnable {
@Override
public void run ( ) {
while ( true ) {
synchronized ( PcSync. class ) {
if ( queue. size ( ) > 0 ) {
queue. remove ( ) ;
System. out. println ( "消费一个,消费后有商品" + queue. size ( ) + "个" ) ;
SleepTools. randomMs ( 400 ) ;
} else {
System. out. println ( "空了,不能再消费了..." ) ;
}
}
}
}
}
}
二、wait-notify
public class PcWaitNotify {
static int MAX = 10 ;
static Queue< Object> queue = new ArrayDeque < > ( MAX) ;
public static void main ( String[ ] args) {
Producer p = new Producer ( ) ;
Consumer c1 = new Consumer ( ) ;
Consumer c2 = new Consumer ( ) ;
new Thread ( p) . start ( ) ;
new Thread ( p) . start ( ) ;
new Thread ( c1) . start ( ) ;
new Thread ( c2) . start ( ) ;
}
static class Producer implements Runnable {
@Override
public void run ( ) {
while ( true ) {
synchronized ( queue) {
if ( queue. size ( ) >= MAX) {
queue. notifyAll ( ) ;
} else {
queue. add ( new Object ( ) ) ;
System. out. println ( "生产者生产了 1 个,现在有:" + queue. size ( ) + " 个商品..." ) ;
SleepTools. randomMs ( 500 ) ;
}
}
}
}
}
static class Consumer implements Runnable {
@Override
public void run ( ) {
while ( true ) {
synchronized ( queue) {
if ( queue. size ( ) <= 0 ) {
queue. notifyAll ( ) ;
} else {
queue. remove ( ) ;
System. out. println ( "消费者消费了 1 个,现在有:" + queue. size ( ) + " 个商品..." ) ;
SleepTools. randomMs ( 500 ) ;
}
}
}
}
}
}
三、Condition
public class PcCondition {
private static ReentrantLock lock = new ReentrantLock ( ) ;
private static Condition consumer = lock. newCondition ( ) ;
private static Condition producer = lock. newCondition ( ) ;
private static LinkedList< Object> buffer = new LinkedList < > ( ) ;
private static final int MAX = 5 ;
public static void main ( String[ ] args) {
new Thread ( new Producer ( ) ) . start ( ) ;
new Thread ( new Producer ( ) ) . start ( ) ;
new Thread ( new Consumer ( ) ) . start ( ) ;
new Thread ( new Consumer ( ) ) . start ( ) ;
}
static class Producer implements Runnable {
@Override
public void run ( ) {
while ( true ) {
lock. lock ( ) ;
try {
while ( buffer. size ( ) >= MAX) {
System. out. println ( "满了..." ) ;
try {
producer. await ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
if ( buffer. size ( ) < MAX) {
buffer. add ( new Object ( ) ) ;
System. out. println ( "生产一个...生产后数量是" + buffer. size ( ) ) ;
consumer. signalAll ( ) ;
SleepTools. randomMs ( 5000 ) ;
}
} finally {
lock. unlock ( ) ;
}
SleepTools. randomMs ( 5 ) ;
}
}
}
static class Consumer implements Runnable {
@Override
public void run ( ) {
while ( true ) {
lock. lock ( ) ;
try {
while ( buffer. size ( ) <= 0 ) {
System. out. println ( "空了..." ) ;
try {
consumer. await ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
if ( buffer. size ( ) > 0 ) {
buffer. removeFirst ( ) ;
System. out. println ( "消费一个...消费后数量是" + buffer. size ( ) ) ;
producer. signalAll ( ) ;
SleepTools. randomMs ( 5000 ) ;
}
} finally {
lock. unlock ( ) ;
}
}
}
}
}
四、同步队列
public class Pc {
private static AtomicInteger integer = new AtomicInteger ( 0 ) ;
public static void main ( String[ ] args) {
BlockingQueue< Integer> blockingQueue = new LinkedBlockingQueue < > ( 100 ) ;
Producer p = new Producer ( blockingQueue) ;
Consumer c1 = new Consumer ( blockingQueue) ;
Consumer c2 = new Consumer ( blockingQueue) ;
new Thread ( p) . start ( ) ;
new Thread ( p) . start ( ) ;
new Thread ( c1) . start ( ) ;
new Thread ( c2) . start ( ) ;
}
static class Producer implements Runnable {
BlockingQueue< Integer> blockingQueue;
Producer ( BlockingQueue blockingQueue) {
this . blockingQueue = blockingQueue;
}
@Override
public void run ( ) {
while ( true ) {
int i = integer. getAndIncrement ( ) ;
blockingQueue. add ( i) ;
System. out. println ( "生产者生产商品,编号为" + i) ;
SleepTools. randomMs ( 5000 ) ;
}
}
}
static class Consumer implements Runnable {
BlockingQueue< Integer> blockingQueue;
Consumer ( BlockingQueue blockingQueue) {
this . blockingQueue = blockingQueue;
}
@Override
public void run ( ) {
while ( true ) {
Integer element = null;
try {
element = blockingQueue. take ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
System. out. println ( "消费者消费一个,编号为" + element) ;
SleepTools. randomMs ( 5000 ) ;
}
}
}
}
五、有bug的情况
public class PcConditionBug {
private static ReentrantLock lock = new ReentrantLock ( ) ;
private static Condition condition = lock. newCondition ( ) ;
private static LinkedList< Object> buffer = new LinkedList < > ( ) ;
private static final int MAX = 5 ;
public static void main ( String[ ] args) {
new Thread ( new Producer ( ) ) . start ( ) ;
new Thread ( new Producer ( ) ) . start ( ) ;
new Thread ( new Consumer ( ) ) . start ( ) ;
new Thread ( new Consumer ( ) ) . start ( ) ;
}
static class Producer implements Runnable {
@Override
public void run ( ) {
while ( true ) {
lock. lock ( ) ;
try {
while ( buffer. size ( ) >= MAX) {
System. out. println ( "满了..." ) ;
try {
condition. await ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
if ( buffer. size ( ) < MAX) {
buffer. add ( new Object ( ) ) ;
System. out. println ( "生产一个...生产后数量是" + buffer. size ( ) ) ;
condition. signal ( ) ;
SleepTools. randomMs ( 50 ) ;
}
} finally {
lock. unlock ( ) ;
}
}
}
}
static class Consumer implements Runnable {
@Override
public void run ( ) {
while ( true ) {
lock. lock ( ) ;
try {
while ( buffer. size ( ) <= 0 ) {
System. out. println ( "空了..." ) ;
try {
condition. await ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
if ( buffer. size ( ) > 0 ) {
buffer. removeFirst ( ) ;
System. out. println ( "消费一个...消费后数量是" + buffer. size ( ) ) ;
condition. signal ( ) ;
SleepTools. randomMs ( 50 ) ;
}
} finally {
lock. unlock ( ) ;
}
}
}
}
}
对比
方案 优点 缺点 synchronized 代码简单,方法被同步执行,线程安全 相对没那么灵活 wait-notify 容易学习了解同步机制 需要注意死锁的情况,用singal要小心 Condition 容易控制 注意自由一个Condition的时候有可能会死锁 同步队列 不需要考虑线程安全,线程安全容器实现了线程间的同步,编码简单 不利于了解同步细节
如果要实现安全高效的,建议使用同步队列,另外双Condition也很好