我正在实现一个用于处理大量市场数据馈送的线程池,并且对重新使用实现了可运行且提交到线程池以供执行的工作程序实例的策略有疑问。在我的情况下,我只有一种类型的工作程序,它采用String并将其解析以创建Quote对象,然后将Quote对象设置在正确的Security上。给定来自提要的数据量,每秒可能有多达1,000个报价要处理,我看到了两种创建提交到线程池的工作程序的方法。

第一种选择是,每次从底层套接字中检索行时,只需创建一个Worker的新实例,然后将其添加到线程池中,该线程池将在执行run方法后最终被垃圾回收。但这让我开始思考性能,每秒实例化1,000个Worker类的新实例真的有意义吗?人们本着与线程池相同的精神,知道是否有一个可运行的池或队列是否也是一种常见的模式,所以我可以回收我的工作人员以避免对象创建和垃圾回收。我看到这种实现的方式是在返回run()方法之前,Worker将自己添加回可用的worker队列,然后在处理新的提要行而不是创建Worker的新实例时从中获取该 worker 。

从性能的角度来看,我采用第二种方法会有所收获,还是第一种方法更有意义?以前有人实现过这种模式吗?

谢谢-邓肯

最佳答案

为此,我使用了一个名为Java Chronicle的库。它被设计为每秒持久存储一百万个报价,并将其排入队列,而不会产生任何重大垃圾。

我有一个here演示,其中它以每秒百万条消息的速度发送带有纳秒级定时信息的对象之类的报价,并且它可以在32 MB堆的JVM中发送数千万,而不会触发较小的收集。在我的 super 本上,往返延迟小于90%的时间不到0.6微秒。 ;)



我强烈建议不要用垃圾填充CPU缓存。实际上,我避免使用任何会产生大量垃圾的构造。您可以构建一个系统,该系统在每个事件端到端创建少于一个对象。我的伊甸园大小大于一天中产生的垃圾量,因此无需担心GC太小或太满。



五年前,我用Java编写了一个有利可图的低延迟交易系统。当时它以60微秒的滴答速度足够快,可以使用Java进行交易,但是如今您可以做得更好。

如果您需要低延迟的市场数据处理系统,这就是我的方法。您可能也会发现我在JavaOne上所做的演示很有趣。

http://www.slideshare.net/PeterLawrey/writing-and-testing-high-frequency-trading-engines-in-java

编辑我已经添加了这个parsing example

ByteBuffer wrap = ByteBuffer.allocate(1024);
ByteBufferBytes bufferBytes = new ByteBufferBytes(wrap);
byte[] bytes = "BAC,12.32,12.54,12.56,232443".getBytes();

int runs = 10000000;
long start = System.nanoTime();
for (int i = 0; i < runs; i++) {
    bufferBytes.reset();
    // read the next message.
    bufferBytes.write(bytes);
    bufferBytes.position(0);
    // decode message
    String word = bufferBytes.parseUTF(StopCharTesters.COMMA_STOP);
    double low = bufferBytes.parseDouble();
    double curr = bufferBytes.parseDouble();
    double high = bufferBytes.parseDouble();
    long sequence = bufferBytes.parseLong();
    if (i == 0) {
        assertEquals("BAC", word);
        assertEquals(12.32, low, 0.0);
        assertEquals(12.54, curr, 0.0);
        assertEquals(12.56, high, 0.0);
        assertEquals(232443, sequence);
    }
}
long time = System.nanoTime() - start;
System.out.println("Average time was " + time / runs + " nano-seconds");

用-verbose:gc -Xmx32m设置时,它会打印
Average time was 226 nano-seconds

注意:没有触发任何GC。

关于java - 在线程池中重用Runnable是否有意义?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19121856/

10-09 16:53