本人技术博客: http://demi-panda.com
本例介绍一个特殊的队列:BlockingQueue,如果BlockingQueue是空的,从BlockingQueue取东西的操作将会被阻断进入 等待状态,直到BlockingQueue进了东西才会被唤醒,同样,如果BlockingQueue是满的,任何试图往里存东西的操作也会被阻断进入等 待状态,直到BlockingQueue里有空间时才会被唤醒继续操作。
本例再次实现前面介绍的篮子程序,不过这个篮子中最多能放得苹果数不是1,可以随意指定。当篮子满时,生产者进入等待状态,当篮子空时,消费者等待。
BlockingQueue定义的常用方法如下:
add(anObject):把anObject加到BlockingQueue里,如果BlockingQueue可以容纳,则返回true,否则抛出异常。
offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false。
put(anObject):把anObject加到BlockingQueue里,如果BlockingQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里有空间再继续。
poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null。
take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的对象被加入为止。
BlockingQueue有四个具体的实现类,根据不同需求,选择不同的实现类:
ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小。其所含的对象是以FIFO(先入先出)顺序排序的。
LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue 有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定。其所含的对象是以FIFO顺序排序 的。
PriorityBlockingQueue:类似于LinkedBlockingQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数所带的Comparator决定的顺序。
SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的。
LinkedBlockingQueue和ArrayBlockingQueue比较起来,它们背后所用的数据结构不一样,导致 LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于 ArrayBlockingQueue。
package com.yoyosys.smartstorage.consumer;
import java.util.concurrent.BlockingQueue;
/**
* to-do.
*
* @author Denghaiping
* @version 1.0
*/
public class Fetcher implements Runnable
{
@SuppressWarnings("unused")
private BlockingQueue<String> queue = null ;
public Fetcher(BlockingQueue<String> queue)
{
this.queue = queue;
}
public void run()
{
try {
while (true) {
queue.put("segment-name-"+i);
System.out.println("ThreadName : "+ Thread.currentThread().getName() +" 抓取完成");
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
*/
package com.yoyosys.smartstorage.consumer;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* to-do.
*
* @author Denghaiping
* @version 1.0
*/
public class Indexer implements Runnable
{
private BlockingQueue<String> queue ;
public Indexer(BlockingQueue<String> queue)
{
this.queue = queue;
}
public void run()
{
try {
while(true) {
Thread.sleep(1000);
String name = queue.take();
System.out.println("ThreadName : " +Thread.currentThread().getName()+ " 索引创建完成 " +name);
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
package com.yoyosys.smartstorage.consumer;
import java.util.concurrent.*;
/**
* to-do.
*
* @author Denghaiping
* @version 1.0
*/
public class TestConsumer
{
private static BlockingQueue<String> queue = new ArrayBlockingQueue<String> (10);
public static void main(String [] args)
{
ExecutorService service = Executors.newCachedThreadPool();
Fetcher producer = new Fetcher(queue);
Indexer consumer = new Indexer(queue);
Indexer consumer1 = new Indexer(queue);
service.submit(producer);
service.submit(consumer);
service.submit(consumer1);
// 程序运行5s后,所有任务停止
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//service.shutdownNow();
}
}
相关推荐
Java中的`java.util.concurrent`包提供了`BlockingQueue`接口,可以方便地实现生产者-消费者模型。生产者将产品放入队列,消费者从队列中取出产品,队列的大小限制了可以同时存储的产品数量,从而实现自动同步。 5...
在项目的"生产者-消费者"代码中,可以预见到它将展示如何创建`BlockingQueue`实例,然后在生产者线程中调用`put`方法向队列添加元素,在消费者线程中调用`take`方法取出元素。同时,可能还会有异常处理和中断机制,...
在Java中,可以使用`BlockingQueue`接口来实现生产者-消费者模式,它已经内置了线程安全的队列操作。生产者可以使用`offer()`方法添加元素,消费者则用`take()`方法取出元素,这两个方法会自动处理等待和唤醒操作。 ...
2. **BlockingQueue接口**:Java并发包`java.util.concurrent`中的`BlockingQueue`接口为生产者-消费者问题提供了一种更为高级且易用的解决方案。`BlockingQueue`实现了线程安全的队列操作,如`put()`(添加元素)和...
`BlockingQueue`接口是最常用的实现方式,它提供了线程安全的数据结构,可以用来作为生产者和消费者之间的缓冲区。例如,我们可以使用`ArrayBlockingQueue`、`LinkedBlockingQueue`等具体实现。 下面通过一个简单的...
`BlockingQueue`是一种线程安全的数据结构,它实现了生产者和消费者之间的阻塞等待。当队列满时,生产者会阻塞直到有空间可以插入;同样,当队列为空时,消费者也会阻塞等待新的数据。 下面是一个简单的多生产者-多...
在计算机科学中,"并发控制-生产者-消费者问题"是一个经典的多线程同步问题,它涉及到了进程通信和资源管理。这个问题的核心在于确保生产者(生成数据的线程)和消费者(消耗数据的线程)能够有效地共享一个有限...
这种特性使得`BlockingQueue`非常适合用于生产者-消费者模式的场景。 #### 2. BlockingQueue的常用方法 `BlockingQueue`接口定义了一系列的方法来支持线程安全的操作: - **add(anObject)**: 将`anObject`添加到`...
本示例中的“生产者-消费者”模型是一种经典的多线程问题,它模拟了实际生产环境中的资源分配与消耗过程。下面我们将详细探讨如何在Java中实现这个模型。 首先,我们要理解生产者-消费者模型的基本概念。在这个模型...
这通常涉及到使用同步队列(如BlockingQueue)等数据结构来控制生产者何时产生数据,消费者何时消费数据。 BlockingQueue是一种线程安全的队列,提供了在生产者和消费者之间阻塞或等待的机制。当队列满了时,生产者...
2. BlockingQueue:Java并发包(java.util.concurrent)中的BlockingQueue接口提供了一种更安全、更高效的方式来处理生产者-消费者问题。它是一个线程安全的数据结构,内部已经实现了线程同步和等待通知机制。生产者...
5. ** 线程安全与同步**:`BlockingQueue`提供了内置的线程同步机制,因此生产者和消费者在操作队列时不会出现数据不一致的情况。这比使用传统的`synchronized`关键字或者`wait()`/`notify()`来手动管理线程同步更...
`BlockingQueue`接口提供了线程安全的队列,自动处理了等待和唤醒操作,是实现生产者-消费者模型的一种高效方式。 4. **条件变量**:`wait()`, `notify()`和`notifyAll()`是基于条件变量的,它们可以使得线程在特定...
Java 并发集合:ConcurrentHashMap 和 ...Java 并发集合(ConcurrentHashMap 和 BlockingQueue)提供了高效的并发操作和线程安全机制,广泛应用于多种场景,例如多线程编程、数据存储和访问、生产者-消费者模式等。
线程池可以配合生产者消费者模式,例如通过提交任务到线程池来实现生产者,线程池中的工作线程充当消费者角色。 在使用生产者消费者模式时,需要注意以下几点: - **线程安全**:确保所有的操作都是线程安全的,...
在Java中,`BlockingQueue`接口是实现生产者消费者模式的理想选择。`BlockingQueue`提供了线程安全的队列操作,并且内置了阻塞机制。当队列满时,`put()`方法会使得生产者线程自动阻塞,直至队列有空位;当队列空时...
在Java中,可以通过多种方式实现生产者-消费者模型,包括但不限于使用`wait()`和`notify()`方法、`BlockingQueue`接口、`Semaphore`类以及`ReentrantLock`和`Condition`组合等。 #### 使用`wait()`和`notify()` 这...
在生产者-消费者场景下,BlockingQueue 能够确保生产者线程在队列满时不会过度生产,而消费者线程在队列为空时也不会过度消耗资源。示例代码展示了如何创建生产者和消费者线程,它们共享同一个 BlockingQueue 实例,...
这个库提供了多种工具类,如Semaphore(信号量)、BlockingQueue(阻塞队列)和Condition(条件变量),这些都可以用来实现生产者-消费者模型。 1. **BlockingQueue**: 阻塞队列是一种特殊的队列,它具有线程安全的...