Java:线程生成器使用者等待生成数据的最有效方法是什么

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

场景:

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

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

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

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

private BlockingQueue data; private final LinkedBlockingQueue results = new LinkedBlockingQueue(); @Override public void run() { while (!data.isEmpty()) { for (LocalTime dataTime : data) { if (new LocalTime().isAfter(dataTime)) { results.put(result); } } } } 

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

 while (!data.isEmpty()) 

从之前的问题开始。

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

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

你应该使用take

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

BlockingQueue的#取

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

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

 public void run(){ LocalTime timestamp = null; while((timestamp = data.take()) != null){ ... } } 

根据我们的评论更新:

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

然后我跟进:

那么您需要根据LocalDate的时间戳进行优先级排队吗?

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

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

 BlockingQueue data = new PriorityBlockingQueue<>(); OR INVERSE THE ORDER BlockingQueue data = new PriorityBlockingQueue<>(0, (a,b) -> b.compareTo(a)); 

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

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

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

你需要使用take方法。 当队列为空时,此方法将阻塞。 这将替换您的检查以查看队列是否为空。

其次,为什么需要时间戳? 如果时间戳是为了确保你处理请求,他命令将它们放入队列然后你不需要它,因为队列是FIFO并且是为并发multithreading环境做的。 如果时间戳来自系统外部,某些外部时间戳,请求可能无序,但需要按顺序处理,则此BlockQueue不会删除它。 您可能需要PriorityBlockingQueue ,您可以按时间戳为请求设置优先级。 因此要么删除时间戳,要么使用PriorityBlockingQueue