java - 阻塞队列轮询方法在多个线程期间返回null

标签 java spring multithreading spring-boot blockingqueue

我们已经使用阻塞队列,执行程序框架和将来在应用程序中实现了多线程。
当用户需要任何数据时,我们都会向执行器框架提交任务,该执行器框架连接到数据库,查询数据并将数据流回。
我们有一个方法,该方法读取此数据并将其写入servletoutputstrean。


public long writeData(ServletOutputStream sos, BlockingQueue < T > blockingQueue, Future < Boolean > future) {

    try (final JsonWriter writer = new JsonWriter(new OutputStreamWriter(sos, UTF_8))) {

        int counter = 0;
        while (true) {
            Optional.ofNullable(blockingqueue.poll()).ifPresent(entityobj - > {
                gson.toJson(entityobj, entityobj.getclass(), writer);
                Counter++;
            });



            if (blockingqueue.isEmpty() && future.isDone() && future.get()) {
                if (count == 0) {
                    Log.error("data not read properly");
                }
                break;
            }
        }
    } catch (Exception e) {
        log.error(e);
    }
    return counter;
}

当执行blockingqueue.poll()时,存储库线程有时仍未加载数据。到下一个if块出现时,阻塞队列为空,并且future完成,因此控制退出while循环。
没有响应写入流。无论如何要处理这种怪异的行为
有大量记录时不会发生这种情况。

最佳答案

When blockingqueue.poll() is being executed, there are times data is still not loaded by the repositorythread. By the time the next if block comes, blocking queue is empty and future is completed so control gets out of while loop.


您的代码中存在竞争条件,这使事情变得更加复杂:
if (blockingqueue.isEmpty() && /* race here */ future.isDone() && future.get()) {
blockingqueue.isEmpty()有可能返回true,然后作业在future.isDone()调用发生之前完成,导致代码过早退出,队列中留有一个元素。
@Willis提到的“流末尾”对象是一个不错的选择,但是一个简单的解决方案是像下面这样重构您的代码:
boolean futureDone = future.isDone();
entity = blockingqueue.poll();
if (entity == null) {
   if (futureDone) {
      break;
   }
} else {
   // process entity
}
这样可以确保您始终从阻止队列中删除最后一个项目之前检查 future 是否已经完成,从而消除了比赛。您可能需要再进行一次民意测验,但那样很好。
顺便说一句,如果此代码确实在旋转,则应在轮询中添加某种超时以减慢它的速度,并且不占用CPU:
entity = blockingqueue.poll(50, TimeUnit.MILLISECONDS);

关于java - 阻塞队列轮询方法在多个线程期间返回null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63061559/

相关文章:

java - 尝试从 Player 类中抽取时 Player 不会移动

Spring MVC - 包含静态文件/javascript、css

java - 是否可以使用 JSR 303 字段验证来验证 List<String> 值

java - 调试Grails时速度慢

java - "Couldn' t 查找具有权限 com.google.firebase.database.provider 的提供商的元数据”

java - 将序列化的 HTML 时间字段转换为 java.time.LocalTime

c++ - 找出调用 __fastfail 的原因

java - 是否应该为 Java 中的线程命名以便于调试?

java - 现代 JVM 中的双重检查锁定

java - 在 Java 中使用 SOAP Web 服务(具有安全性)