Java:在时间关键型应用程序中实现高性能多线程的最佳方法是什么?
我正在使用Java8开发一个网络代理应用程序。对于入口,主要逻辑是数据处理循环:在入站队列中获取数据包,处理内容数据(例如协议采用),然后将其放入发送队列。设计中允许使用多个虚拟TCP通道,因此数据处理线程(在数据处理线程列表中)在特定时间段处理一组通道,作为整个作业的一部分(例如,对于具有Java:在时间关键型应用程序中实现高性能多线程的最佳方法是什么?,java,multithreading,concurrency,time-critical,Java,Multithreading,Concurrency,Time Critical,我正在使用Java8开发一个网络代理应用程序。对于入口,主要逻辑是数据处理循环:在入站队列中获取数据包,处理内容数据(例如协议采用),然后将其放入发送队列。设计中允许使用多个虚拟TCP通道,因此数据处理线程(在数据处理线程列表中)在特定时间段处理一组通道,作为整个作业的一部分(例如,对于具有通道的通道。通道ID%NUM_DATA_PROCESSING_THREADS=0,由负载平衡计划程序确定)。通道存储在一个数组中,通过使用通道化的作为单元索引进行访问,该单元由一个类包装,该类提供了诸如注册、
通道的通道。通道ID%NUM_DATA_PROCESSING_THREADS=0
,由负载平衡计划程序确定)。通道存储在一个数组中,通过使用通道化的
作为单元索引进行访问,该单元由一个类包装,该类提供了诸如注册
、取消注册
、getById
、大小
等方法,该实例在程序中称为通道存储
。我需要使用这些方法在主逻辑(数据处理循环)中用不同的线程(至少调度线程、数据处理线程和控制操作线程从GUI中销毁一个通道),然后需要考虑这些线程之间的并发性。
synchronized
或围绕寄存器
、注销
、getById
等的可重入锁。这是最简单且线程安全的方法。但我对锁(CAS)机制存在性能问题,因为我需要在通道存储上执行操作
(尤其是getById
)的频率非常高
executor.execute(runnable)
和/或executor.submit(可调用)将CHANNEL\u STORE
的操作指定给SingleThreadExecutor
。关注的是在数据处理循环中的每个这样的目的地创建可运行/可调用的性能:创建可运行实例并调用执行
–我不知道这会比同步或可重入锁更具扩展性。实际上(到目前为止)有post操作,所以在数据处理循环中只放置RUNABLE,不需要等待可调用的返回,尽管在控制循环中需要post操作。
通道存储
的操作指定给一个专用任务,每次访问通道存储
,将一个任务指示符和一个参数附件放在第一个队列中,然后通过阻塞方法在该队列上执行专用线程循环
并在CHANNEL_STORE
上操作。然后,它将结果放入第二个队列,让指示符继续post操作(但是目前无需)。我认为这是最快的,假设JVM中的阻塞队列是无锁的。这方面的问题是代码非常混乱且容易出错
我目前正在使用流IO进行LAN读/写。如果使用NIO,NIO线程和数据处理线程之间的协调可能会带来额外的复杂性(例如后期操作)。因此我认为这个问题对于时间关键型(基于流的多通道网络)来说是有意义的像我这样的应用程序。如果我很了解您的用例,这是并发编程中的常见问题。一种解决方案是使用环形缓冲区方法,它通常可以很好地解决同步和太多对象创建问题
您可以在lmax Disruptor库中找到这方面的一个很好的实现。请参阅以了解更多信息。但请记住,它不是魔术,必须根据您的用例进行调整。感谢您的推荐。lmax Disruptor似乎适合我的场景,我相信它可能会为我节省大量的时间。但是,文档是不容易理解,在将其应用于我的程序之前,我仍在尝试了解整个过程。一旦我完成,我将接受答案。马丁·福勒(Martin Fowler)写了一篇关于破坏者的好文章,并给出了一些解释和建议()。你还可以找到关于破坏者的更实用的介绍。