C# Java中自适应线程池的设计考虑

C# Java中自适应线程池的设计考虑,c#,java,concurrency,threadpool,C#,Java,Concurrency,Threadpool,我想用Java实现一个线程池,它可以根据提交给它的任务的计算和I/O行为动态调整自身大小 实际上,我希望实现与C#4.0中相同的行为 是否已经有了实现,或者我可以通过使用现有的并发实用程序(例如CachedThreadPool)来实现这种行为 C#版本进行自我检测以实现最佳利用率。Java中提供了什么样的自插装,以及它对性能的影响 在任务发出意图信号的情况下(例如,进入I/O密集型操作、进入CPU密集型操作阶段),执行协作方法是否可行 欢迎提出任何建议 根据评论编辑: 目标情景可能是: 本地文

我想用Java实现一个线程池,它可以根据提交给它的任务的计算和I/O行为动态调整自身大小

实际上,我希望实现与C#4.0中相同的行为

是否已经有了实现,或者我可以通过使用现有的并发实用程序(例如CachedThreadPool)来实现这种行为

C#版本进行自我检测以实现最佳利用率。Java中提供了什么样的自插装,以及它对性能的影响

在任务发出意图信号的情况下(例如,进入I/O密集型操作、进入CPU密集型操作阶段),执行协作方法是否可行

欢迎提出任何建议

根据评论编辑

目标情景可能是:

  • 本地文件爬网和处理
  • 网页爬行
  • 多Web服务访问和聚合
CachedThreadPool的问题在于,当所有现有线程都被阻塞时,它会启动新线程—您需要对其设置显式边界,但仅此而已


例如,我一行要访问100个web服务。如果我创建一个100CTP,它将启动100个线程来执行该操作,那么大量的多个I/O请求和数据传输肯定会相互绊倒。对于静态测试用例,我可以进行实验并找出最佳池大小,但我希望它能够自适应地确定并以某种方式应用。

我认为您应该以特定于平台的方式监控CPU利用率。了解您拥有多少CPU/内核,并监视负载。当您发现负载较低,但仍有更多工作时,请创建新线程,但不能超过num CPU的x倍(例如,x=2)

如果你真的想考虑IO线程,尝试找出每个线程在池耗尽时的状态,并从总数中扣除所有等待线程。然而,一个风险是,你会因为接受太多任务而耗尽内存。

给出的示例如下

Result[] a = new Result[N];
for(int i=0;i<N;i++) {
    a[i] = compute(i);
}
Result[]a=新结果[N];

对于(inti=0;i考虑创建一个映射,其中键是瓶颈资源

提交到池中的每个线程都将提交一个资源,这是它的瓶颈,即“CPU”、“网络”、“C:\”等


您可以从每个资源只允许一个线程开始,然后慢慢地增加,直到工作完成率停止增加。CPU之类的东西可以有一个底层的核心计数。

让我介绍另一种方法。拥有一个单线程池是一个很好的抽象,但它的性能不是很好,特别是在作业非常复杂的情况下IO绑定-那么就没有好的方法来调整它,它很容易放大池大小以最大化IO吞吐量,但是您会遇到太多线程切换等问题

相反,我建议您看看ApacheMina框架的体系结构,从中获得灵感。()这是一个高性能的web框架——他们将其描述为服务器框架,但我认为他们的体系结构也适用于反向场景,如爬行和多服务器客户端。(实际上,您甚至可以在项目中开箱即用。)

他们将Java NIO(非阻塞I/O)库用于所有IO操作,并将工作划分为两个线程池:一组小而快的套接字线程和一组大而慢的业务逻辑线程。因此,各层如下所示:

  • 在网络端,有一大组NIO通道,每个通道都有一个消息缓冲区
  • 一个小的套接字线程池,通过通道列表循环。他们唯一的任务是检查套接字,并将任何数据移出消息缓冲区-如果消息完成,则关闭它并传输到作业队列。这些人速度很快,因为他们只需推送位,跳过IO上阻塞的任何套接字
  • 序列化所有消息的单个作业队列
  • 一个大的处理线程池,它将消息从队列中拉出来,解析它们,并执行所需的任何处理

这有助于实现非常好的性能—IO被分离到自己的层中,您可以调整套接字线程池以最大化IO吞吐量,并单独调整处理线程池以控制CPU/资源利用率。

我想这是我的问题之一,如何对每个线程进行检测(以独立于平台的方式)繁忙和阻塞比率。我不是建议你对线程进行指令插入。相反,使用OS API从线程外部找出线程是否正在等待。我想这就是指令插入。不,不,不,指令插入是指当你将代码放入线程本身时,即在线程中运行的代码中插入更多代码。我会我建议您不要使用任何标准API,也不要使用任何注入。在Linux上,读取/proc//task//stat以了解线程是否正在运行。我不确定您打算从不断缩小的线程池中获得什么好处。线程不做任何事的成本实际上是零(最大的影响可能来自线程本地缓存)。与CachedThreadPool的thread timeout选项提供的好处相同。你的意思是像cached thread pool一样吗?默认的空闲超时是一分钟,但你可以更改。也许你可以解释一下你要寻找的行为?我跟踪了链接,它只是说它有多酷,但不是什么。不确定你为什么要安装它说到线程,也许它在Java和C#中的含义有所不同……实际上,你的回答与我的问题无关。我知道如何处理固定池和缓存池,但我希望在两者之间找到一些东西——考虑CPU利用率、I/O阻塞和I/O传输属性,并“安排”实现最大化um CPU和最大
// defined earlier
int procs = Runtime.getRuntime().availableProcessors();
ExecutorService service = Executors.newFixedThreadPool(proc);

// main loop.
Future<Result>[] f = new Future<Result>[N];
for(int i = 0; i < N; i++) {
    final int i2 = i;
    a[i] = service.submit(new Callable<Result>() {
        public Result call() {
            return compute(i2);
        }
    }
}
Result[] a = new Result[N];
for(int i = 0; i < N; i++) 
    a[i] = f[i].get();