注意事项:
- 保证生产者不会在缓冲区满的时候继续向缓冲区放入数据,而消费者也不会在缓冲区空的时候,消耗数据
- 当缓冲区满的时候,生产者会进入休眠状态,当下次消费者开始消耗缓冲区的数据时,生产者才会被唤醒,开始往缓冲区中添加数据;当缓冲区空的时候,消费者也会进入休眠状态,直到生产者往缓冲区中添加数据时才会被唤醒
应用场景
- 任务的处理时间比较长的情况下:比如上传附件并处理,那么这个时候可以将用户上传和处理附件分成两个过程,用一个队列暂时存储用户上传的附近,然后立刻返回用户上传成功,然后有专门的线程处理队列中的任务
1、用阻塞队列实现多生产者多消费者问题
package com.nowcoder.community.thread;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
public class Producer implements Runnable{
private ArrayBlockingQueue<Integer> queue;
public Producer(ArrayBlockingQueue<Integer> queue){
this.queue=queue;
}
public void run(){
Random random=new Random();
while (true){
try{
Thread.sleep(100);
if(queue.size()==10){
System.out.println("the queue is full");
}
int item=random.nextInt(100);
queue.put(item);
System.out.println("producer:"+Thread.currentThread().getName()+" produce:" + item+";the size of the queue:" + queue.size());
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
package com.nowcoder.community.thread;
import java.util.concurrent.ArrayBlockingQueue;
public class Consumer implements Runnable{
private ArrayBlockingQueue<Integer> queue;
public Consumer(ArrayBlockingQueue<Integer> queue){
this.queue=queue;
}
@Override
public void run() {
while (true){
try{
Thread.sleep(100);
if (queue.size()==0){
System.out.println(("=============the queue is empty,the consumer thread is waiting................"));
}
Integer item = queue.take();
System.out.println("consumer:" + Thread.currentThread().getName() + " consume:" + item+";the size of the queue:" + queue.size());
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
package com.nowcoder.community.thread;
import java.util.concurrent.ArrayBlockingQueue;
public class Test {
public static void main(String[] args) {
ArrayBlockingQueue<Integer> queue=new ArrayBlockingQueue<Integer>(10);
Thread producer1=new Thread(new Producer(queue));
Thread producer2=new Thread(new Producer(queue));
Thread producer3=new Thread(new Producer(queue));
Thread producer4=new Thread(new Producer(queue));
Thread producer5=new Thread(new Producer(queue));
producer1.start();
producer2.start();
producer3.start();
producer4.start();
producer5.start();
Thread consumer1=new Thread(new Consumer(queue));
Thread consumer2=new Thread(new Consumer(queue));
consumer1.start();
consumer2.start();
try {
producer1.join();
producer2.join();
producer3.join();
producer4.join();
producer5.join();
consumer1.join();
consumer2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2、利用信号量实现
中国读者常常不明白这一同步机制为什么叫PV操作,原来这是狄克斯特拉用荷兰文定义的,因为在荷兰文中,通过叫passeren,释放叫vrijgeven,PV操作因此得名。这是在计算机术语中不是用英语表达的极少数的例子之一。
package com.nowcoder.community.thread;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Semaphore;
/**
* 容器用于存放数据
*/
public class Container {
Semaphore fullCount=new Semaphore(0);
Semaphore emptyCount=new Semaphore(10);
Semaphore isUse=new Semaphore(1);
List list=new LinkedList();
public void put(Integer val){
try{
emptyCount.acquire();
isUse.acquire();
list.add(val);
System.out.println("producer--"+Thread.currentThread().getName()+"--put:" + val+"===size:"+list.size());
}catch (InterruptedException e){
e.printStackTrace();
}finally {
isUse.release();
fullCount.release();
}
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
public Integer get(){
Integer val1=0;
try{
fullCount.acquire();
isUse.acquire();
val1 = (Integer) list.remove(0);
System.out.println("consumer--"+ Thread.currentThread().getName()+"--take:" + val1+"===size:"+list.size());
}catch (InterruptedException e){
e.printStackTrace();
}finally {
isUse.release();
emptyCount.release();
}
return val1;
}
}
package com.nowcoder.community.thread;
import java.util.Random;
public class Producer implements Runnable {
private Container container;
public Producer(Container container){
this.container=container;
}
@Override
public void run() {
while (true){
container.put(new Random().nextInt(100));
}
}
}
package com.nowcoder.community.thread;
public class Consumer implements Runnable{
private Container container;
public Consumer(Container container){
this.container=container;
}
@Override
public void run() {
while (true){
Integer val=container.get();
}
}
}