自适应多线程可伸缩的生产者消费者队列服务(二)

章节介绍

本项目适合新入门Java Spring 及多线程的用户,实现过程不复杂,但需要对Spring 提供的队列接口及线程有深刻的理解。本节主要介绍项目的目录结构,接口,依赖配置。

项目目录结构

Example目录结构

多线程可伸缩的生产消费队列示例目录结构

Queue 目录结构

多线程可伸缩的生产消费队列目录结构

BlockingQueue 接口介绍

该队列主要依赖于BlockQueue接口,要先了解该接口的定义,才能明白我们为什么要使用那些接口方法。
java.util.concurrent.BlockingQueue接口是Java并发编程中一个非常重要的组件,它结合了队列的行为与线程阻塞机制。这个接口提供了在多线程环境中高效、安全地进行元素的生产与消费的方法。以下是BlockingQueue接口中需要实现的一些关键方法及其功能描述:

1. void put(E e) throws InterruptedException

  • 作用:将一个元素添加到队列尾部,如果队列满,则调用线程将被阻塞直到队列中有可用的空间。
  • 注意事项:如果当前线程被中断,会抛出InterruptedException异常并清除中断状态。

2. E take() throws InterruptedException

  • 作用:从队列头部移除并返回一个元素,如果队列为空,则调用线程将被阻塞直到队列中有可用的元素。
  • 注意事项:同样,如果当前线程被中断,会抛出InterruptedException异常并清除中断状态。

3. boolean offer(E e)

  • 作用:尝试将一个元素添加到队列尾部,如果成功则返回true,如果队列已满则立即返回false
  • 注意事项:这是一个非阻塞操作。

4. E poll()

  • 作用:尝试从队列头部移除并返回一个元素,如果队列为空则立即返回null
  • 注意事项:这也是一个非阻塞操作。

5. boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException

  • 作用:尝试将一个元素添加到队列尾部,等待指定的时间,如果成功则返回true,如果队列在超时前未满则返回false
  • 注意事项:如果当前线程被中断,会抛出InterruptedException异常并清除中断状态。

6. E poll(long timeout, TimeUnit unit) throws InterruptedException

  • 作用:尝试从队列头部移除并返回一个元素,等待指定的时间,如果队列在此期间变得非空则返回元素,否则返回null
  • 注意事项:如果当前线程被中断,会抛出InterruptedException异常并清除中断状态。

7. int remainingCapacity()

  • 作用:返回队列剩余的容量。

8. int drainTo(Collection<? super E> c)

  • 作用:将队列中的所有元素移除并添加到指定的集合中,返回移动的元素数量。

9. int drainTo(Collection<? super E> c, int maxElements)

  • 作用:将队列中的最多maxElements个元素移除并添加到指定的集合中,返回实际移动的元素数量。

10. boolean add(E e)

  • 作用:等同于offer(E e),但抛出IllegalStateException如果队列已满。

11. E remove()

  • 作用:等同于poll(),但抛出NoSuchElementException如果队列为空。

12. E element()

  • 作用:等同于peek(),但抛出NoSuchElementException如果队列为空。

13. E peek()

  • 作用:查看队列头部的元素,但不移除它,如果队列为空则返回null

14. 其他方法
除了上述方法,BlockingQueue还继承了Queue接口的方法,如size(), isEmpty(), contains(Object o), toArray(), toArray(T[] a), toString(), remove(Object o), containsAll(Collection<?> c), addAll(Collection<? extends E> c), retainAll(Collection<?> c), removeAll(Collection<?> c), 和 clear(),这些方法提供了额外的集合操作功能。

通过实现BlockingQueue接口,不同的队列类能够提供阻塞和非阻塞的入队和出队操作,支持多种队列策略,如FIFO(先进先出)、LIFO(后进先出),以及优先级队列等。

当前项目仅需要通过使用remainingCapacity获取剩余容量,评估队列忙闲;使用poll(long timeout, TimeUnit unit) 获取任务;使用offer(E e, long timeout, TimeUnit unit)添加任务。

Maven 依赖配置

Example

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.davin</groupId>
        <artifactId>framework</artifactId>
        <version>${revision}</version>
    </parent>

    <artifactId>example</artifactId>
    <packaging>jar</packaging>

    <properties>
        <java.version>11</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <org-redisson.version>3.17.6</org-redisson.version>
        <com-davin-queue.version>1.0.0-SNAPSHOT</com-davin-queue.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>${org-redisson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.davin</groupId>
            <artifactId>queue</artifactId>
            <version>${com-davin-queue.version}</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.7.10</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>com.davin.DemoApplication</mainClass>
                    <fork>true</fork>
                    <!--
                    Enable the line below to have remote debugging of your application on port 5005
                    <jvmArguments>-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005</jvmArguments>
                    -->
                </configuration>
            </plugin>
        </plugins>
    </build>
    <profiles>
    </profiles>
</project>

Queue Maven

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>com.davin</groupId>
    <artifactId>framework</artifactId>
    <version>1.0.0</version>
  </parent>

  <groupId>com.davin</groupId>
  <artifactId>queue</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <properties>
    <java.version>11</java.version>
    <maven.compiler.source>${java.version}</maven.compiler.source>
    <maven.compiler.target>${java.version}</maven.compiler.target>
    <spring-boot-dependencies.version>2.7.10</spring-boot-dependencies.version>
    <spring-boot-autoconfigure.version>2.7.10</spring-boot-autoconfigure.version>
    <slf4j.version>1.7.36</slf4j.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>${spring-boot-dependencies.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${slf4j.version}</version>
    </dependency>
  </dependencies>
</project>

我们的服务仅依赖 spring-boot-dependencies 及 slf4j-api,无其他依赖,这样做的好处有如下几点:

  1. 减少冲突:较少的依赖意味着更少的版本冲突可能性。当多个库之间有不兼容的版本要求时,冲突就可能发生,这可能导致构建失败或运行时错误。
  2. 加快构建速度:更少的依赖通常意味着更快的构建过程,因为Maven不需要下载和解析大量的依赖元数据和JAR文件。
  3. 简化项目配置:需要维护的依赖越少,POM(Project Object Model)文件就越简单,更容易理解和维护。
  4. 降低安全风险:较少的外部依赖降低了引入已知漏洞或恶意代码的风险。每个新增的依赖都可能是一个潜在的安全隐患。
  5. 提高稳定性:少量的依赖通常会使得系统更加稳定,因为出现问题的组件也更少。
  6. 易于升级和迁移:当需要更新依赖库或迁移到新的架构时,较少的依赖可以使这一过程更加简单和快速。
  7. 改善性能:过多的依赖可能会导致应用程序启动时间变长,或者在运行时消耗更多的内存资源。精简依赖有助于提升应用性能。
  8. 促进代码质量和可读性:使用最少的必要依赖可以鼓励编写更加简洁、模块化和可重用的代码。
  9. 增强团队协作:当依赖关系明确且最小化时,团队成员之间的协作变得更加顺畅,因为每个人都清楚项目的确切依赖。

继续阅读

上一篇: 自适应多线程可伸缩的生产者消费者队列服务(一)
下一篇: 自适应多线程可伸缩的生产者消费者队列服务(三)
目录: 详见 分布式可伸缩队列

猜你喜欢

转载自blog.csdn.net/s011803/article/details/139534972