JDK为我们提供了多个阻塞队列的实现,什么是阻塞队列呢? 我们都知道队列就是一组数据的集合,而阻塞队列的意思是,当你往队列中取数据时,如果没有数据,你将被阻塞,一直等到拿到数据为止;
今天我们就来看一下比较常用的遵循先进先出的阻塞队列LinkedBlockingQueue;
//同步阻塞队列
//可以看到,当调用take()方法去拿数据时,如果里面没有数据,将造成阻塞
public static void blockingQueue(){
final BlockingQueue<String> queue = new LinkedBlockingQueue<>();
ExecutorService exec = Executors.newCachedThreadPool();
//一个线程不断的往队列中取东西
exec.execute(new Runnable() {
public void run() {
while( !Thread.currentThread().isInterrupted() ){
try {
String value = queue.take();
System.out.println("线程"+Thread.currentThread()+"拿到数据:"+value);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
//一个线程不断的往队列中放东西
exec.execute(new Runnable() {
public void run() {
while( !Thread.currentThread().isInterrupted() ){
try {
TimeUnit.MILLISECONDS.sleep(1000);
int number = new Random().nextInt(1000);
System.out.println("写入数据:"+number);
queue.put(number+"");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
简单吧!一个线程写数据,一个线程读数据,当读数据的线程调用queue.take()往队列中拿数据时,如果队列中没有数据,它就一直阻塞,直到写数据的线程通过queue.put()方法写入数据为止! 是不是比我们自己写wait()和notify()要简单好用的多呢?!
对比上一篇文章的生产者消费者的实现,如果我们采用阻塞队列来实现的话,会变成什么样子呢?我们来看一下吧!
//餐厅
class BlockingRestaurant{
public BlockingQueue<String> queue = new LinkedBlockingQueue<>();
}
//食物消费者(顾客)
class BlockingConsumer{
//在这家餐厅就餐
private BlockingRestaurant res = null;
public BlockingConsumer( BlockingRestaurant res ) {
this.res = res;
}
//吃食物方法
public void eat() throws InterruptedException{
while( !Thread.currentThread().isInterrupted() ){
if( res.queue.take()!=null ){
System.out.println("开始吃食物...");
TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000));//吃食物时间
System.out.println("食物吃完了!...");
}
}
}
}
//食物提供者(厨师)
class BlockingProvider{
//在这家餐厅工作
private BlockingRestaurant res = null;
public BlockingProvider( BlockingRestaurant res ) {
this.res = res;
}
public void fry() throws InterruptedException{//炒菜
while( !Thread.currentThread().isInterrupted() ){
System.out.println("开始做食物...");
TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000));
res.queue.put("一份食物");
System.out.println("食物做完了!...");
}
}
}
//经典生产者与消费者演示(采用队列)
public static void producerByQueue(){
ExecutorService exec = Executors.newCachedThreadPool();
BlockingRestaurant res = new BlockingRestaurant();
final BlockingConsumer consumer = new BlockingConsumer(res);
final BlockingProvider provider = new BlockingProvider(res);
exec.execute(new Runnable() {
public void run() {
try {
consumer.eat();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
exec.execute(new Runnable() {
public void run() {
try {
provider.fry();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
简单多了吧! Ok,这就是LinkedBlockingQueue的使用方法, 后面我们会再介绍优先级队列,延时队列等等多种队列,它们将实现更有趣的功能!