您的位置:首页 > 编程语言 > Java开发

多线程经典问题之生产者消费者问题的JAVA实现

2016-04-20 15:20 731 查看
生产者消费者问题作为多线程中helloworld,是每个多线程开发人员入门必须掌握的。生产者消费者问题在开发当中应用广泛,如最常接触的线程池实现,多种阻塞消息队列中。下面介绍一下用java.util.concurrent.BlockingQueue实现和自己编写一个Storage实现简单部分类似BlockingQueue的功能。

1.BlockingQueue
public class ProducerAndConsumerImplByBlockingQueue {

public static void main(String[] args) {
//Storage store = new Storage();
BlockingQueue<String> queue = new LinkedBlockingQueue<String>(20);//定义BlockingQueue的大小为20

Thread t1 = new Thread(new Producer1(queue));
Thread t2 = new Thread(new Consumer1(queue));
t1.start();
t2.start();
}
}

/**
* 生产者线程
* @author YZJ
*
*/
class Producer1 implements Runnable {

private BlockingQueue<String> queue;

public Producer1(BlockingQueue<String> queue){
this.queue = queue;
}

@Override
public void run() {
int i = 1;
while(true){
try {
System.out.println("生产产品:"+i);
queue.put("产品"+i++);
Thread.sleep(200);//线程睡眠时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
}

/**
* 消费者线程
* @author YZJ
*
*/
class Consumer1 implements Runnable {

private BlockingQueue<String> queue;

public Consumer1(BlockingQueue<String> queue){
this.queue = queue;
}

@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
System.out.println("消费产品:"+queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}


LinkedBlockingQueue用链表的方式实现FIFO,采用ReentrantLock进行同步,关于ReentrantLock机制大家可自行查阅相关文章,作者在后续中也会对ReentrantLock原理进行简单分析。除LinkedBlockingQueue以外,BlockingQueue的常用实现还有ArrayBlockingArray,内部采用数组实现,类似于LinkedList和ArrayList的关系。其他实现还有PriorityBlocingQueue,SynchronousQueue。PriorityBlocingQueue于采用自然排序或自定义comparator实现排序而非FIFO;SynchronousQueue则是实现一放一取的队列。

2.自定义Storage

public class ProducerAndConsumer {

public static void main(String[] args) {
Storage store = new Storage();
Thread t1 = new Thread(new Producer(store));
Thread t2 = new Thread(new Consumer(store));
t1.start();
t2.start();
}

}

/**
* 生产者线程
* @author YZJ
*
*/
class Producer implements Runnable {

private Storage storage;

public Producer(Storage storage){
this.storage = storage;
}

@Override
public void run() {
int i = 1;
while(true){
storage.push("产品"+i++);

}

}

}

/**
* 消费者线程
* @author YZJ
*
*/
class Consumer implements Runnable {

private Storage storage;

public Consumer(Storage storage){
this.storage = storage;
}

@Override
public void run() {
while(true){
storage.pop();
}
}

}

/**
* 阻塞队列,存放产品
* @author YZJ
*
*/
class Storage{

private List<String> list = new ArrayList<String>();

public void push(String product){
synchronized(this){
list.add(product);
System.out.println("生产产品:"+product);
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if(list.size()==20){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
}

}

public void pop(){
synchronized(this){
if(list.size()>0){
System.out.println("消费产品:"+list.get(0));
list.remove(0);
}else{
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
}
}

public List<String> getList(){
return list;
}
}

Storage同样采用FIFO策略,简单实现阻塞队列,若需要更改策略,可修改pop中提取策略即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: