java 多线程生产者_Java多线程之 生产者与消费者

JDK的Concurrent包中的BlockingQueue接口,增加了可阻塞的插入和获取等操作。当队列为空时,获取操作被阻塞;当队列满时,插入操作被阻塞。通过BlockingQueue可以和方便的实现生产者与消费者模式。

LinkedBlockingQueue(一个BlockingQueue的实现类)通过分别在插入和获取操作上加不同的Reentrant锁,来实现插入操作的同步和获取操作的同步,即插入操作和获取操作是可以同时进行的。如下是根据LinkedBlockingQueue源码自己实现的一个简单的阻塞队列:

import java.util.LinkedList;

import java.util.concurrent.atomic.AtomicInteger;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.ReentrantLock;

public class MyBlockQueue {

private LinkedList queue = new LinkedList();

private final ReentrantLock putLock = new ReentrantLock();

private final ReentrantLock takeLock = new ReentrantLock();

private final Condition empty = takeLock.newCondition();

private final Condition full = putLock.newCondition();

private final int capacity = 5;

private AtomicInteger count = new AtomicInteger();

/*释放因列表满而等待的线程*/

protected void signalFull() {

final ReentrantLock putLock = this.putLock;

try {

putLock.lockInterruptibly();

full.signal();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

finally {

putLock.unlock();

}

}

/*释放因列表空而阻塞的读线程*/

protected void signalEmpty() {

final ReentrantLock takeLock = this.takeLock;

try {

takeLock.lockInterruptibly();

empty.signal();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

finally {

takeLock.unlock();

}

}

public void put(E e) {

if(e == null) return;

final ReentrantLock putLock = this.putLock;

int c = -1;

try {

putLock.lockInterruptibly();

final Condition full = this.full;

final AtomicInteger count = this.count;

while(count.get() == capacity) {

full.await();

}

queue.add(e);

c = count.getAndIncrement();//获取更新之前的值

if(c+1 < capacity) {//进行put操作后队列未满,释放full

full.signal();

}

} catch (InterruptedException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}finally {

putLock.unlock();

}

if(c==0){//在put操作之前有因为队列空而阻塞的线程,进行释放

signalEmpty();

}

}

public E take() {

E e = null;

final ReentrantLock takeLock = this.takeLock;

final Condition empty = this.empty;

final AtomicInteger count = this.count;

int c = -1;

try {

takeLock.lockInterruptibly();

while (count.get() == 0) {

empty.await();

}

e = queue.get(0);

queue.remove(0);

c = count.getAndDecrement();

if(c>1) {//在出队列之前,队列中的元素个数大于1,即在出队之后元素个数大于0

empty.signal();

}

} catch (InterruptedException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

finally {

takeLock.unlock();

}

if(c == capacity) {//在进行get之前有线程因为队列满而阻塞

signalFull();

}

return e;

}

}

利用MyBlockQueue实现的生产者消费者模式:

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.atomic.AtomicInteger;

public class Producer implements Runnable {

private AtomicInteger count = new AtomicInteger();

private int id;

//private BlockingQueue blockQueue;

private MyBlockQueue blockQueue;

@Override

public void run() {

// TODO Auto-generated method stub

while(true) {

int x = count.incrementAndGet();

String str = x + "";

try {

blockQueue.put(str);

System.out.println("Producer" + id + " produce: " + str);

Thread.sleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

public Producer(MyBlockQueue blockQueue, int id) {

super();

this.blockQueue = blockQueue;

this.id = id;

}

}

public class Consumer implements Runnable {

private int id;

//private BlockingQueue blockQueue;

private MyBlockQueue blockQueue;

public Consumer(int id, MyBlockQueue blockQueue) {

super();

this.id = id;

this.blockQueue = blockQueue;

}

@Override

public void run() {

// TODO Auto-generated method stub

while(true) {

try {

String str = blockQueue.take();

System.out.println("Consumer" + id + " consume:" + str);

Thread.sleep(500);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

@Test

public void testProducerAndConsumer() throws InterruptedException {

//BlockingQueue blockQueue = new LinkedBlockingQueue(5);

MyBlockQueue blockQueue = new MyBlockQueue();

for(int i=0; i<1; ++i) {

Thread t1 = new Thread(new Producer(blockQueue, i));

t1.start();

Thread t2 = new Thread(new Consumer(i, blockQueue));

t2.start();

t1.join();

t2.join();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值