Java:线程生产者消费者等待生成数据的最有效方法是什么

per*_*kss 6 java multithreading producer-consumer blockingqueue java-7

使用BlockingQueue消耗生成的数据时,等待数据出现的最有效方法是什么?

场景:

步骤1)数据列表将是添加时间戳的数据存储.这些时间戳需要按最接近当前时间优先级排序.此列表可能为空.线程将时间戳插入其中.生产

步骤2)我想在另一个线程中使用此处的数据,该线程将从数据中获取时间戳并检查它们是否在当前时间之后.消费者然后生产

步骤3)如果它们在当前时间之后,则将它们发送到另一个线程以供消费和处理.在此处理时间戳数据后,从步骤1数据存储中删除.消费然后编辑原始列表.

在下面的代码中,数据字段引用步骤1中的数据存储.结果是在当前时间之后已发送的时间戳列表.步骤2.然后将结果消耗步骤3.

private BlockingQueue<LocalTime> data;
private final LinkedBlockingQueue<Result> results = new LinkedBlockingQueue<Result>();

@Override
public void run() {
  while (!data.isEmpty()) {
    for (LocalTime dataTime : data) {
      if (new LocalTime().isAfter(dataTime)) {
        results.put(result);
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

问题 等待数据列表中可能可能为空的数据的最有效方法是什么?专注于:

while (!data.isEmpty())
Run Code Online (Sandbox Code Playgroud)

以前的问题.

Joh*_*int 5

什么是等待生成数据的最有效方法

BlockingQueue具有阻塞功能,该功能将挂起等待队列不为空或未满的线程.在你的情况下,你在消耗CPU的队列上旋转.这不是优选的.

你应该用take.

挂起检索并删除此队列的头部,必要时等待,直到元素可用.

BlockingQueue的#取

这是等待队列中元素的最有效方法,因为挂起线程不消耗cpu.将新项目放入队列后,将唤醒等待的线程.

然后你可以使用put哪个具有相同的等待语义,take但仅限于队列未满.

public void run(){
   LocalTime timestamp = null;
   while((timestamp = data.take()) != null){
      ...
   }
}
Run Code Online (Sandbox Code Playgroud)

根据我们的评论更新:

但在这种情况下,时间戳按顺序创建并添加.但是未来时间戳可能会更少.例如,头节点将来是2分钟,第二节点是1分钟,所以第二个节点想要先处理

然后我的跟进:

那么你需要根据LocalDate的时间戳优先排队吗?

不确定你是使用JodaTime或Java 8中的LocalDate,让我们假设后者.

您可以使用PriorityBlockingQueue具有相同阻塞语义的a.但是,BlockingQueue的优先级方面将根据定义的顺序排列元素.在您的情况下,使用LocalDate您可以拥有从最老到最小或最小到最旧的元素.

BlockingQueue<LocalDate> data = new PriorityBlockingQueue<>(); 

OR INVERSE THE ORDER

BlockingQueue<LocalDate> data = new PriorityBlockingQueue<>(0, (a,b) -> b.compareTo(a));
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您将LocalDate按其自然顺序处理,而不是按照它们排队的顺序进行处理.

如果您正在使用JodaTime的LocalDate,您可能需要实现自己的Comparator类似于我的第二个示例.

编辑:刚刚意识到你有这个标记为java-7.所以你将使用JodaTime,如果JodaTime LocalDate没有实现Comparable,只需创建自己的.