阻塞队列是一种特殊类型的队列,具有阻塞特性。当队列为空时,消费者线程试图从队列中获取元素时会被阻塞,直到队列中有新的元素加入;当队列已满时,生产者线程试图向队列中添加元素时会被阻塞,直到队列中有空位。
阻塞队列可以通过不同的实现方式来实现,常见的实现方式包括基于数组的实现和基于链表的实现。我们将使用基于数组的方式来实现一个简单的阻塞队列。
下面是一个简单的基于数组的阻塞队列的Java代码示例:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BlockingQueue<T> {
private T[] queue;
private int capacity;
private int size;
private int head;
private int tail;
private Lock lock;
private Condition notEmpty;
private Condition notFull;
public BlockingQueue(int capacity) {
this.capacity = capacity;
queue = (T[]) new Object[capacity];
size = 0;
head = 0;
tail = 0;
lock = new ReentrantLock();
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
public void enqueue(T item) throws InterruptedException {
lock.lock();
try {
while (size == capacity) {
notFull.await();
}
queue[tail] = item;
tail = (tail + 1) % capacity;
size++;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public T dequeue() throws InterruptedException {
lock.lock();
try {
while (size == 0) {
notEmpty.await();
}
T item = queue[head];
head = (head + 1) % capacity;
size--;
notFull.signal();
return item;
} finally {
lock.unlock();
}
}
}在这个示例中,我们使用了一个基于数组的队列来实现阻塞队列,并使用了ReentrantLock和Condition来实现线程间的同步和通信。
阻塞队列在多线程编程中有着广泛的应用场景,其中包括但不限于以下几个方面:
下面是一个简单的示例代码,演示了如何使用阻塞队列实现生产者-消费者模式:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ProducerConsumerExample {
private static final int CAPACITY = 10;
private static BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(CAPACITY);
public static void main(String[] args) {
Thread producer = new Thread(() -> {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread consumer = new Thread(() -> {
try {
consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
producer.start();
consumer.start();
}
private static void produce() throws InterruptedException {
int value = 0;
while (true) {
queue.put(value);
System.out.println("Produced: " + value);
value++;
Thread.sleep(1000);
}
}
private static void consume() throws InterruptedException {
while (true) {
int value = queue.take();
System.out.println("Consumed: " + value);
Thread.sleep(2000);
}
}
}在这个示例中,我们创建了一个容量为10的阻塞队列,并分别启动了生产者线程和消费者线程,生产者线程负责生产数据,将数据放入阻塞队列中,而消费者线程负责消费数据,从队列中取出数据进行处理。
阻塞队列的实现原理涉及到线程间的同步和通信机制。在Java中,常用的实现方式包括使用锁和条件变量、使用内置的阻塞队列类等。无论采用何种实现方式,关键在于保证生产者和消费者之间的线程安全和数据可靠性。
在使用阻塞队列时,需要注意以下几点:
阻塞队列在实际应用中有着广泛的应用场景,其中包括但不限于以下几个方面:
以下是一个简单的示例代码,演示了如何使用阻塞队列实现多线程任务调度:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TaskScheduler {
private static final int THREAD_POOL_SIZE = 3;
private static final int TASK_QUEUE_CAPACITY = 10;
private static final BlockingQueue<Runnable> taskQueue = new ArrayBlockingQueue<>(TASK_QUEUE_CAPACITY);
private static final ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
public static void main(String[] args) {
startTaskConsumer();
submitTasks();
}
private static void startTaskConsumer() {
for (int i = 0; i < THREAD_POOL_SIZE; i++) {
executor.execute(() -> {
while (true) {
try {
Runnable task = taskQueue.take();
task.run();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
});
}
}
private static void submitTasks() {
for (int i = 0; i < 20; i++) {
final int taskId = i;
taskQueue.offer(() -> {
System.out.println("Task " + taskId + " executed by " + Thread.currentThread().getName());
});
}
}
}在这个示例中,我们创建了一个简单的任务调度器,使用阻塞队列存储待执行的任务,并创建了一个线程池来执行任务。每个线程从阻塞队列中获取任务,并执行任务的逻辑。