什么是多线程的最佳替代方案?

时间:2015-07-07 08:40:39

标签: java multithreading concurrency actor

目前我们在应用程序(Java)中使用线程。但是一次创建了大约1000个(或更多)线程。这个线程应该处理数据并将其存储在db中。

这会占用更多内存和I / O.

这可能是最好的选择吗? 可伸缩性,一致性和性能是主要要求。

4 个答案:

答案 0 :(得分:17)

你试过thread pools吗?线程池由合理数量的线程(足以使用所有处理器,但不多于)和重新使用线程(再次减少开销)组成,以执行大量任务< / em>同时。

这是一个给你一个想法的小例子

ExecutorService executor = Executors.newFixedThreadPool(5);
Runnable job = new Runnable() {
     public void run() {
        // do some work
     }
}
executor.execute(job);

如果查看ScheduledThreadPoolExecutor,您会发现许多用于执行和安排作业的功能。

答案 1 :(得分:13)

尝试查看Actor model

actor模型是一种并发编程模型,其中工作负载分布在并行运行的实体之间,称为 actors

这是一个模型,其中没有共享状态,actor被隔离,信息可以以消息的形式流动。

玩家收到这些消息,只能对消息中的数据进行操作(计算或处理数据),向其他玩家发送消息或创建新的演员。

这个模型是对互斥锁和线程的高级抽象,它消除了开发人员的复杂性,它主要是为了建立高可用性和竞争性的电信系统,爱立信于1973年在Erlang上建立。 / p>

Actors是非常轻量级的并发实体。它们使用事件驱动的接收循环以异步方式处理消息。对消息进行模式匹配是表达演员行为的便捷方式。它们提高了抽象级别,使编写,测试,理解和维护并发和/或分布式系统变得更加容易。您可以专注于工作流 - 消息在系统中的流动方式 - 而不是线程,锁和套接字IO等低级原语。

Java / Scala 中,您可以找到基于此actor模型构建的Akka framework

答案 2 :(得分:9)

使用线程池。这样,您就可以定义要运行的多个线程。每个新任务都被放入队列并等待,直到线程完成其旧任务,从而可以自由地处理新任务。

这是可扩展的,因为您可以定义要运行的线程数。您可以在具有少量处理内核的设备上选择少数线程来节省内存并减少同步开销,或者在具有多个内核的设备上选择多个线程。所以例如如果你在具有4核和超线程的设备上运行它,选择8个线程,如果你在具有48个硬件线程的设备上运行它,那么选择48个线程。

性能通常比为每个任务启动新线程更好,因为启动和杀死线程确实有一些开销。线程池重用线程,因此没有那个开销。

它也是一致的,因为Java标准库中有一个线程池实现。

答案 3 :(得分:5)

我认为您不需要替代多线程,只需要更高效的线程实现。

Quasar 光纤(即轻量级线程)添加到JVM ,其中您可以创建数百万而非少数数百,因此您可以获得相同的异步框架性能,而不会放弃语言中可用的线程抽象和常规命令控制流构造(序列,循环等)。

它还将JVM / JDK的线程及其光纤统一在一个公共链接接口,因此它们可以无缝地互操作,并为这个统一的概念提供java.util.concurrent的移植。这也意味着您的移植工作量将是最小的(如果有的话)。

在股线(纤维或普通线)之上,Quasar还提供完全成熟的Erlang式演员(请参阅here与Akka进行比较),阻止 Go类似于频道数据流编程,因此您可以选择最适合您的技能和需求的并发编程范例,而不必强制使用。

它还为流行和标准技术提供绑定(作为Comsat项目的一部分),因此您可以保留代码资产,因为移植工作量很小(如果有的话) 。出于同样的原因,如果您选择,也可以轻松选择退出。

目前,Quasar对Pulsar项目下的 Java 7 8 Clojure 具有绑定和JetBrains'Kotlin。基于JVM字节码检测,如果存在集成模块,Quasar可以使用任何JVM语言,并且它提供了构建其他模块的工具。

从Java9开始,检测将是自动的,不再需要集成模块。