# Java `LinkedBlockingQueue`

> 原文： [https://www.programiz.com/java-programming/linkedblockingqueue](https://www.programiz.com/java-programming/linkedblockingqueue)

#### 在本教程中，我们将借助示例学习`LinkedBLockingQueue`类及其方法。

Java `Collections`框架的`LinkedBlockingQueue`类使用链表提供阻塞队列实现。

它实现了 [Java `BlockingQueue`接口](/java-programming/blockingqueue "Java BlockingQueue Interface")。

![ArrayBlockingQueue implements the BlockingQueue interface in Java.](img/7062cb98a9dbc593873ba5a06482eae5.png)

* * *

## 创建`LinkedBlockingQueue`

为了创建链接的阻塞队列，我们​​必须导入`java.util.concurrent.LinkedBlockingQueue`包。

这是我们如何在 Java 中创建链接的阻塞队列的方法：

**1.没有初始容量**

```java
LinkedBlockingQueue<Type> animal = new LinkedBlockingQueue<>(); 
```

在此，默认初始容量为`2 ^ 31 -1`。

**2.具有初始容量**

```java
LinkedBlockingQueue<Type> animal = new LinkedBlockingQueue<>(int capacity); 
```

这里，

*   `Type` - 链接的阻塞队列的类型
*   `capcity` - 链接的阻塞队列的大小

例如，

```java
// Creating String type LinkedBlockingQueue with size 5
LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);

// Creating Integer type LinkedBlockingQueue with size 5
LinkedBlockingQueue<Integer> age = new LinkedBlockingQueue<>(5); 
```

**注意**：不必提供链表的大小。

* * *

## `LinkedBlockingQueue`的方法

`LinkedBlockingQueue`类提供[`BlockingQueue`接口](/java-programming/blockingqueue "Java BlockingQueue Interface")中所有方法的实现。

这些方法用于从链接的阻塞队列中插入，访问和删除元素。

另外，我们还将学习两种方法`put()`和`take()`，它们支持链接的阻塞队列中的阻塞操作。

这两种方法将链接的阻塞队列与其他典型队列区分开来。

* * *

### 插入元素

*   `add()` - 将指定的元素插入链接的阻塞队列。 如果队列已满，它将引发异常。
*   `offer()` - 将指定的元素插入链接的阻塞队列。 如果队列已满，则返回`false`。

例如：

```java
import java.util.concurrent.LinkedBlockingQueue;

class Main {
    public static void main(String[] args) {
        LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);

        // Using add()
        animals.add("Dog");
        animals.add("Cat");

        // Using offer()
        animals.offer("Horse");
        System.out.println("LinkedBlockingQueue: " + animals);
    }
} 
```

**输出**

```java
LinkedBlockingQueue: [Dog, Cat, Horse] 
```

* * *

### 访问元素

*   `peek()` - 从链接的阻塞队列的最前面返回一个元素。 如果队列为空，则返回`null`。
*   `iterator()` - 返回一个迭代器对象，以按顺序访问链接的阻塞队列中的元素。 如果队列为空，则抛出异常。 我们必须导入`java.util.Iterator`包才能使用它。

例如：

```java
import java.util.concurrent.LinkedBlockingQueue;
import java.util.Iterator;

class Main {
    public static void main(String[] args) {
        LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);

        // Add elements
        animals.add("Dog");
        animals.add("Cat");
        animals.add("Horse");
        System.out.println("LinkedBlockingQueue: " + animals);

        // Using peek()
        String element = animals.peek();
        System.out.println("Accessed Element: " + element);

        // Using iterator()
        Iterator<String> iterate = animals.iterator();
        System.out.print("LinkedBlockingQueue Elements: ");

        while(iterate.hasNext()) {
            System.out.print(iterate.next());
            System.out.print(", ");
        }
    }
} 
```

**输出**：

```java
LinkedBlockingQueue: [Dog, Cat, Horse]
Accessed Element: Dog
LinkedBlockingQueue Elements: Dog, Cat, Horse, 
```

* * *

### 删除元素

*   `remove()` - 返回指定的元素并将其从链接的阻塞队列中移除。 如果队列为空，则抛出异常。
*   `poll()` - 返回指定的元素并将其从链接的阻塞队列中移除。 如果队列为空，则返回`null`。
*   `clear()` - 从链接的阻塞队列中删除所有元素。

例如：

```java
import java.util.concurrent.LinkedBlockingQueue;

class Main {
    public static void main(String[] args) {
        LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);

        animals.add("Dog");
        animals.add("Cat");
        animals.add("Horse");
        System.out.println("LinkedBlockingQueue " + animals);

        // Using remove()
        String element1 = animals.remove();
        System.out.println("Removed Element:");
        System.out.println("Using remove(): " + element1);

        // Using poll()
        String element2 = animals.poll();
        System.out.println("Using poll(): " + element2);

        // Using clear()
        animals.clear();
        System.out.println("Updated LinkedBlockingQueue " + animals);
    }
} 
```

**输出**：

```java
LinkedBlockingQueue: [Dog, Cat, Horse]
Removed Elements:
Using remove(): Dog
Using poll(): Cat
Updated LinkedBlockingQueue: [] 
```

* * *

## `put()`和`take()`方法

在多线程进程中，我们可以使用`put()`和`take()`阻止一个线程的操作，使其与另一个线程同步。 这些方法将等待直到可以成功执行。

* * *

### `put()`方法

要将指定的元素插入到链接的阻塞队列的末尾，我们使用`put()`方法。

如果链接的阻塞队列已满，它将等待，直到链接的阻塞队列中有足够的空间来插入元素。

例如：

```java
import java.util.concurrent.LinkedBlockingQueue;

class Main {
    public static void main(String[] args) {
        LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);

       try {
        // Add elements to animals
           animals.put("Dog");
           animals.put("Cat");
           System.out.println("LinkedBlockingQueue: " + animals);
        }
        catch(Exception e) {
            System.out.println(e);
        }
    }
} 
```

**输出**：

```java
LinkedBlockingQueue: [Dog, Cat] 
```

在此，如果`InterruptedException`方法在等待时被中断，则可能会抛出`InterruptedException`。 因此，我们必须将其封装在`try..catch`块中。

* * *

### `take()`方法

要从链接的阻塞队列的前面返回并删除一个元素，我们可以使用`take()`方法。

如果链接的阻塞队列为空，它将等待，直到要删除的链接阻塞队列中的元素为止。

例如：

```java
import java.util.concurrent.LinkedBlockingQueue;

class Main {
    public static void main(String[] args) {
        LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);

       try {
           //Add elements to animals
           animals.put("Dog");
           animals.put("Cat");
           System.out.println("LinkedBlockingQueue: " + animals);

           // Remove an element
           String element = animals.take();
           System.out.println("Removed Element: " + element);
           System.out.println("New LinkedBlockingQueue: " + animals);
        }
        catch(Exception e) {
            System.out.println(e);
        }
    }
} 
```

**输出**：

```java
LinkedBlockingQueue: [Dog, Cat]
Removed Element: Dog
New LinkedBlockingQueue: [Cat] 
```

在这里，如果`take()`方法在等待时被中断，则会抛出`InterrupedException`。 因此，我们必须将其封装在[H​​TG2]块内。

* * *

## 其他方法

| 方法 | 内容描述 |
| --- | --- |
| `contains(element)` | 在链接的阻塞队列中搜索指定的元素。 如果找到该元素，则返回`true`，否则返回`false`。 |
| `size()` | 返回链接的阻塞队列的长度。 |
| `toArray()` | 将链接的阻塞队列转换为数组并返回该数组。 |
| `toString()` | 将链接的阻塞队列转换为字符串 |

* * *

## 为什么要使用`LinkedBlockingQueue`？

`LinkedBlockingQueue`使用链表作为其内部存储。

它被视为**线程安全的**集合。 因此，它通常用于多线程应用中。

假设一个线程正在将元素插入队列，而另一个线程正在从队列中删除元素。

现在，如果第一个线程比第二个线程慢，则链接的阻塞队列可使第二个线程等待，直到第一个线程完成其操作。