lof*_*ses 15 java queue performance multithreading
这是我在stackoverflow上的第一篇文章...我希望有人可以帮助我
我对Java 6有很大的性能回归LinkedBlockingQueue.在第一个线程中,我生成了一些我推入队列的对象.在第二个线程中,我将这些对象拉出来.当频繁调用take()方法时,会发生性能回归LinkedBlockingQueue.我监控了整个程序,并且该take()方法总体上占据了最多的时间.吞吐量从~58Mb/s到0.9Mb/s ......
队列弹出并使用此类中的静态方法调用方法
public class C_myMessageQueue {
private static final LinkedBlockingQueue<C_myMessageObject> x_queue = new LinkedBlockingQueue<C_myMessageObject>( 50000 );
/**
* @param message
* @throws InterruptedException
* @throws NullPointerException
*/
public static void addMyMessage( C_myMessageObject message )
throws InterruptedException, NullPointerException {
x_queue.put( message );
}
/**
* @return Die erste message der MesseageQueue
* @throws InterruptedException
*/
public static C_myMessageObject getMyMessage() throws InterruptedException {
return x_queue.take();
}
}
Run Code Online (Sandbox Code Playgroud)
如何调整take()方法以达到至少25Mb/s,或者是否有一个我可以使用的类,它将在"队列"满或空时阻塞.
亲切的问候
巴特
PS:抱歉我的英语不好,我来自德国;)
Dim*_*eou 16
您的生产者线程只是放置了比消费者消耗的元素更多的元素,因此队列最终达到其容量限制,因此生产者等待.
从现在起巩固我原来的答案我们基本上已经全面了解:
LinkedBlockingQueue通过执行极快的put()s 来达到(每个队列都有一个)的固有吞吐量限制,即使是连续的take()s,没有进一步处理,也无法跟上.(顺便说一下,这表明在这个结构中,无论如何,在你的JVM和机器上,put()s至少比读取的成本稍高一些).SynchronousQueue,ConcurrentLinkedQueue以及即将TransferQueuejsr166y的).一些建议:
/在John W.正确地指出我的原始答案是误导之后更新
我通常建议不要在性能敏感的代码区域使用 LinkedBlockingQueue,而使用 ArrayBlockingQueue。它将提供更好的垃圾收集配置文件,并且比 LinkedBlockingQueue 对缓存更友好。
尝试使用 ArrayBlockingQueue 并测量性能。
LinkedBlockingQueue 的唯一优点是它可以是无界的,但这很少是您真正想要的。如果您遇到消费者失败并且队列开始备份的情况,则有界队列允许系统优雅地降级,而不是冒可能在队列无界时发生 OutOfMemoryErrors 的风险。
这里有几件事可以尝试:
更换LinkedBlockingQueue用的ArrayBlockingQueue。它没有悬空引用,因此在队列填满时表现更好。具体来说,考虑到 LinkedBlockingQueue 的 1.6 实现,在队列实际变空之前不会发生元素的完全 GC。
如果生产者端始终优于消费者端,请考虑使用drain或drainTo执行“批量”获取操作。
或者,让队列采用消息对象的数组或列表。生产者用消息对象填充列表或数组,每个放置或获取以相同的锁定开销移动多个消息。把它想象成一个秘书递给你一堆“当你外出时”的信息,而不是一次递给你一个。