多线程能提高性能吗?Java场景

3

我有一个 List<Object> objectsToProcess,假设它包含1000000个元素。对于数组中的每个元素,您可以像这样处理:

for(Object : objectsToProcess){
    Go to database retrieve data.
    process
    save data
}

我的问题是:多线程能提高性能吗?我认为处理器默认会分配多个线程,对吗?


1
你是指将1000000个对象进行分区吗? - SMA
是的,如果您有1000000个对象在列表中并且您逐个处理每个对象,则当最后一个对象被处理时,程序将结束。多线程能加速它吗,还是速度会保持不变? - Rory Lester
1
是的,那么尝试将数据分割成10个部分,并创建10个不同的数据库连接。 - SMA
2个回答

10
在所描述的情况下,考虑到进程是一项耗时的任务,并且考虑到CPU有多个核心,多线程确实会提高性能。
处理器并不是分配线程的那个。处理器提供资源(虚拟CPU / 虚拟处理器),可以通过提供多个执行单元/执行上下文由线程使用。程序需要自己创建多个线程,以便同时利用多个CPU核心。
多线程的两个主要原因是:
- 利用多个CPU核心,否则这些核心将闲置或至少无法减少解决给定问题所需的时间 - 如果问题可以划分为可以独立处理的子问题(可以并行化)。 - 使程序同时对多个事物进行操作和反应(即事件线程与Swing工作者)。
有编程语言和执行环境会自动创建线程,以处理可以并行化的问题。Java目前还不是其中之一,但自Java 8以来,它已经朝着这个方向发展,而Java 9可能会带来更多的改进。
通常,您不想拥有比CPU提供的CPU核心更多的线程,原因很简单,线程切换和线程同步是会减慢速度的开销。 java.util.concurrent包提供了许多类,可帮助解决多线程的典型问题。您需要的是一个ExecutorService,将要并行运行和完成的任务分配给它。类Executors提供了用于创建流行类型的ExecutorService的工厂方法。如果您的问题只需要在并行环境下解决,可以选择Executors.newCachedThreadPool()。如果您的问题很紧急,则可以选择Executors.newWorkStealingPool()
因此,您的代码可能如下所示:
final ExecutorService service = Executors.newWorkStealingPool();
for (final Object object : objectsToProcess) {
    service.submit(() -> {
            Go to database retrieve data.
            process
            save data
        }
    });
}

请注意,如果您采用多线程的方法,处理对象的顺序将不再保证。
如果您要处理的对象可以提供并行流,您也可以采用以下方式:
objectsToProcess.parallelStream().forEach(object -> {
    Go to database retrieve data.
    process
    save data
});

这将把处理线程的决策留给虚拟机,通常比我们自己实现多线程更好。
进一步阅读:

1

这取决于时间花费在哪里。

如果你有一堆计算需要执行,将工作分配到更多线程可以帮助,就像你说的每个线程可能在单独的CPU上执行。在这种情况下,拥有比CPU更多的线程是没有价值的。正如Corbin所说,你必须想出如何在线程之间划分工作,并负责启动线程,等待完成和聚合结果。

如果像你的情况一样,你正在等待一个数据库,那么使用线程可能会增加额外的价值。数据库可以并行地处理几个请求(数据库服务器本身是多线程的),因此不用编写

for(Object : objectsToProcess){
    Go to database retrieve data.
    process
    save data
}

如果您需要等待每个响应后再发出下一个请求,那么您需要有多个工作线程同时执行。

 Go to database retrieve data.
 process
 save data

这样可以获得更好的吞吐量。但是,关键在于不要有太多的工作线程。原因如下:

  1. 每个线程使用一些资源,它有自己的堆栈和与数据库的连接。你不会想要 10,000 个这样的线程。
  2. 每个请求在服务器上使用资源,每个连接使用内存,每个数据库服务器只能同时处理一定数量的请求。如果它只能并行处理几十个请求,那么同时提交数千个请求是没有任何好处的。此外,如果数据库是共享的,你可能不想用你的请求饱和数据库,你需要成为一个“好公民”。

总之:通过拥有一定数量的工作线程,您几乎肯定会获得益处。哪些数量的线程有帮助将由因素(例如您拥有的 CPU 数量以及您执行的处理量与 DB 响应时间之间的比率)决定。你只能通过实验来真正确定这个数字,所以让线程数量可配置并进行调查。从 5 开始,然后是 10。随着增加线程数量,注意数据库的负载。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接